美文网首页安卓开发博客
可以代替 onActivityResult 的办法

可以代替 onActivityResult 的办法

作者: 英勇青铜5 | 来源:发表于2018-07-08 19:59 被阅读235次

    1. 代替重写 Activity 的 onActivityResult

    项目中比较多的,某一个Activity使用startActivityForResult()Target Actiivty拿一个结果,之前在网上看到一个方案,通过借助一个无视图的Fragment来进行实现,这样没必要重写onActivityResult(),借鉴下思路,改了下代码,用在了项目中,暂时也没发现有什么问题

    使用场景:同一个进程的中的两个Activity来使用


    1.0 StartForResultManager

    /**
     * @author g&c
     * @date 2018/01/15
     * 避免使用 onActivityResult
     * 通过一个没有视图的 Fragment
     * 从 Target Activity 获取数据
     * <p>
     * 暂时考虑不使用单例,用后即焚
     */
    public class StartForResultManager {
        private static final String TAG = StartForResultManager.class.getSimpleName();
        private StartCallbackFragment mStartCallbackFragment;
    
        /**
         * 跳转 Activity 的 Class 对象
         */
        private Class<?> mTargetClass;
    
        /**
         * 从开始 Activity 传给数据源目标 Activity的数据
         */
        private Bundle mDataBundle;
    
        public static StartForResultManager get() {
            return new StartForResultManager();
        }
    
        private StartForResultManager() {
        }
    
        public StartForResultManager from(Activity activity) {
            mStartCallbackFragment = crateStartCallbackFragment(activity);
            return this;
        }
    
        public StartForResultManager from(Fragment fragment) {
            this.from(fragment.getActivity());
            return this;
        }
    
        public StartForResultManager to(Class<?> clazz) {
            this.mTargetClass = clazz;
            return this;
        }
    
    
        public StartForResultManager bundle(Bundle bundle) {
            mDataBundle = new Bundle(bundle);
            return this;
        }
    
        /**
         * 开启目标 Activity
         *
         * @param callback 结果回调
         */
        public void startForResult(@NonNull CallbackAdapter callback) {
            if (mStartCallbackFragment == null) {
                throw new NullPointerException("From activity is null , forget from() ?");
            }
            Activity activity = mStartCallbackFragment.getActivity();
            if (activity == null) {
                // 若为 Activity 为 Null,说明场景不再适合使用 StartForResultManager
                throw new NullPointerException("Surprise , something is error , perhaps this is love");
            }
            if (mTargetClass == null) {
                throw new NullPointerException("mTargetClass is null , forget to() ?");
            }
            Intent intent = new Intent(activity, mTargetClass);
            if (mDataBundle != null) {
                intent.putExtras(mDataBundle);
            }
            fragmentStartForResult(intent, callback.hashCode(), callback);
        }
    
        /**
         * 创建中间桥梁 Fragment
         *
         * @param activity 启动 Activity :桥梁 Fragment 所依赖的 Activity
         * @return Fragment
         */
        private StartCallbackFragment crateStartCallbackFragment(Activity activity) {
            StartCallbackFragment resultFragment = findStartCallbackFragment(activity);
            if (resultFragment == null) {
                resultFragment = new StartCallbackFragment();
                FragmentManager fragmentManager = activity.getFragmentManager();
                fragmentManager
                        .beginTransaction()
                        .add(resultFragment, TAG)
                        .commitAllowingStateLoss();
                fragmentManager.executePendingTransactions();
            }
            return resultFragment;
        }
    
        /**
         * 查找中间桥梁 Fragment
         *
         * @param activity 启动 Activity
         * @return Fragment
         */
        private StartCallbackFragment findStartCallbackFragment(Activity activity) {
            return (StartCallbackFragment) activity.getFragmentManager().findFragmentByTag(TAG);
        }
    
        /**
         * 通过桥梁 Fragment 启动数据源目标 Activity
         *
         * @param intent      Intent
         * @param requestCode 请求码
         * @param callback    结果回调
         */
        private void fragmentStartForResult(Intent intent, int requestCode, CallbackAdapter callback) {
            mStartCallbackFragment.startForResult(intent, requestCode, callback);
        }
    
        /**
         * 结果回调适配
         */
        public static class CallbackAdapter implements Callback {
    
            @Override
            public void onResultError() {
    
            }
    
            @Override
            public void onActivityResult(int resultCode, Intent data) {
    
            }
        }
    
        /**
         * 结果回调接口
         */
        private interface Callback {
    
            /**
             * 当拿结果出现错误时
             * 当 Intent data 为 null 时
             */
            void onResultError();
    
            /**
             * 结果回调
             *
             * @param resultCode 结果码
             * @param data       数据
             */
            void onActivityResult(int resultCode, Intent data);
        }
    }
    

    1.1 StartCallbackFragment

    无视图的中间桥梁 Fragment

    /**
     * @author g&c
     * @date 2018/01/15
     * 桥梁,没有界面
     * 利用 startForResult(),onActivityResult()方法
     * 从目标数据源 TargetActivity 获取数据,返回到启动的 Activity
     */
    public final class StartCallbackFragment extends Fragment {
        /**
         * 存放 Callback
         */
        private SparseArray<StartForResultManager.CallbackAdapter> mCallbackArr;
    
        public StartCallbackFragment() {
            mCallbackArr = new SparseArray<>();
        }
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true);
        }
    
        /**
         * StartCallbackFragment 开启目标 Activity
         *
         * @param intent      意图
         * @param requestCode 请求码
         * @param callback    回调
         */
        public void startForResult(Intent intent, int requestCode,
                                   StartForResultManager.CallbackAdapter callback) {
            mCallbackArr.put(requestCode, callback);
            startActivityForResult(intent, requestCode);
        }
    
        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            // Callback 结果回调
            StartForResultManager.CallbackAdapter callback = mCallbackArr.get(requestCode);
            if (callback == null) {
                return;
            }
            // 移除 Callback
            mCallbackArr.remove(requestCode);
            if (data == null) {
                // 回调错误方法
                callback.onResultError();
                return;
            }
            // 结果回调
            callback.onActivityResult(resultCode, data);
        }
    }
    

    CallbackAdapter有两个方法,使用时,若不关心拿到不到结果的情况,就没必要重写onResultError()方法,只关心onActivityResult()就可以


    2. 使用

    2.1 来源Activity

    public class StartCallbackActivity extends AppCompatActivity {
        private TextView mTvContent;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_start_callback);
            initView();
        }
    
        private void initView() {
            Button bt = findViewById(R.id.activity_start_callback_bt);
            mTvContent = findViewById(R.id.activity_start_callback_tv);
            bt.setOnClickListener(v -> start("116", "20180116 You happy, You ok"
                    , StartCallbackResultActivity.class));
    
            Button bt2 = findViewById(R.id.activity_start_callback_bt2);
            bt2.setOnClickListener(v -> start("117", "20180116 This is love"
                    , StartCallbackResult2Activity.class));
        }
    
        private void start(String key, String value, Class<?> cla) {
            // 数据
            Bundle b = new Bundle();
            b.putString(key, value);
    
            // 跳转
            StartForResultManager
                    .get()
                    .from(StartCallbackActivity.this)
                    .to(cla)
                    .bundle(b)
                    .startForResult(new StartForResultManager.CallbackAdapter() {
                        @Override
                        public void onActivityResult(int resultCode, Intent data) {
                            super.onActivityResult(resultCode, data);
                            String str = data.getStringExtra("text");
                            if (resultCode == Activity.RESULT_OK && !TextUtils.isEmpty(str)) {
                                mTvContent.setText(str);
                            }
                        }
    
                        @Override
                        public void onResultError() {
                            super.onResultError();
                            String str = "没有返回有效数据";
                            mTvContent.setText(str);
                        }
                    });
        }
    }
    

    布局就是两个Button,一个TextView,点击一个Button跳转对应的一个Target Activity,然后在Target Activity使用setResult()来返回结果显示在TextView

    StartCallbackActivity来源 Activity

    StartCallbackResultActivity,StartCallbackResult2Activity为两个不同的 Target Activity


    2.1 Target Activity

    StartCallbackResultActivity中有一个Button,点击将数据返回

    /**
     * @author g&c
     * @date 2018/01/15
     * Target Activity
     * 接收来源 Activity 传递过来的一个字符串
     * 返回给来源 Activity 一个字符串
     */
    public class StartCallbackResultActivity extends AppCompatActivity {
        private String mStringData = "-1";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_start_callback_result);
            getData();
            initView();
        }
    
        private void getData() {
            Intent intent = getIntent();
            if (intent == null) {
                return;
            }
            Bundle extras = intent.getExtras();
            if (extras == null) {
                return;
            }
            mStringData = (String) extras.get("116");
        }
    
        private void initView() {
            Button bt = findViewById(R.id.activity_start_result_bt);
            bt.setOnClickListener(v -> {
                Intent intent = new Intent();
                intent.putExtra("text", "12345678");
                setResult(Activity.RESULT_OK, intent);
                finish();
            });
    
            TextView tv = findViewById(R.id.activity_start_result_tv);
            tv.setText(mStringData);
        }
    }
    

    关键就一个setResult()方法


    3. 最后

    使用说明:

    StartForResultManager必须 调用from()指定来源 Activity,使用to()来指定Target Activity,否则StartForResultManager.startForResult()方法中会抛出NullPointerException,可以看一眼代码

    来源 Activity需要将数据传递到Target Activity,可以使用bundle()传递一个Bundle,若不需要数据,就没必要调用bundle()


    若使用时,有啥问题,或者遇到不适合使用的场景,请留言指出

    相关文章

      网友评论

      • 卤蛋大大:这样做的优点是什么
        JarryLeo:@英勇青铜5 怎么会没啥优点呢?利用无视图fragment注册到activity的fragmentManager;这个fragment有了activity的所有生命周期,和所有的回调方法,包括开启新的页面获取返回结果回调,请求权限结果回调,等等;可以干的事情很多,楼主思路要放开啊:wink:
        JarryLeo:好处就是封装框架可以获取activity的生命周期,让框架自己处理生命周期问题。很多框架注册后需要在onDestroy里面取消注册,利用楼主的方法可以做到框架自己取消注册。还有就是可以封装动态权限框架处理权限请求结果,而不必让用户自己实现权限回调方法,框架可自行处理等等
        英勇青铜5:@卤蛋大大 也没啥优点,就是减少些使用startForResult和onActivityResult两个方法的代码割裂感吧。

      本文标题:可以代替 onActivityResult 的办法

      本文链接:https://www.haomeiwen.com/subject/fttauftx.html