美文网首页Android开发经验谈Android开发Android开发
打开页面自动登录并回来-拦截器(升级版)

打开页面自动登录并回来-拦截器(升级版)

作者: 生活简单些 | 来源:发表于2018-10-27 22:17 被阅读53次

      之前写过一篇文章,讲解如何解耦页面跳转和自动登录,至于思想想必看过那篇文章的人都懂了,简单说就是很多地方都会跳转某个页面(称呼为A页面),但A页面需要登录后才能加载数据,我们不希望发起跳转的页面负责登录判断和登录的工作,即:登录判断和跳转登录应该是A页面自己的份内工作。

    inteceptor.png

      只是,之前的实现有代码侵入性,需要一个让A页面继承一个叫InterceptorActivity的页面(负责注解解析和校验),又恐怕大家项目都已经有了一个所谓的BaseActivity,逼不得已要改动此BaseActivity让其继承InterceptorActivity, 很明显这是有侵入性的。
      新的实现方案是创建一个无UI的Fragment的代理,它负责做真正的startActivityForResult(),随后的activityResult通过它们之间的callback传给创建无UI Fragment的Activity或者Fragment,这原理其实很简单。因此,我们又有了另外一个发现:简化startActivityForResult(), 即:以挂回调的方式处理activityResult。
      其实,Android 6.0权限请求的API跟startActivityForResult()及其类似(requestPermissions (String[] permissions, int requestCode)onRequestPermissionsResult (int requestCode, String permissions[], int[] grantResults)),在此之前也写过篇文章如何通过此原理简化了Android 6.0权限的请求

    如下演示了如何在Activity、Fragment中打开需要先登录的订单详情页,以及不仅要登录还要授权的管理员页面,还有在Activity和Fragment中以挂回调的方式startActivityForResult()接收activityResult:

    activity_result.gif

    1. Activity拦截器新的接入方式:

    // 1. open OrderDetailActivity
    Intent intent = new Intent(context, OrderDetailActivity.class);
    startActivity(intent);
    
    // 2. implementation of OrderDetailActivity
    @InterceptWith(LoginInterceptor.class)
    public class OrderDetailActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_order_detail);
    
            ActivityResult result = new ActivityResult(this);
            result.intercept(new OnInterceptResult(this) {
               
                /**
                 * init data or load data from http and so on after all interceptors is validated.
                 */
                @Override
                public void invoke() {
                    TextView imageView = findViewById(R.id.contentView);
                    imageView.setText("This Is the Order Detail Page");
                }
            });
        }
    }
    

    ActivityResult对象的创建可以在Activity也可在Fragment。
    如果需要多个校验拦截,配置方式跟以前一样(当所有Interceptor都校验通过才会触发invoke()执行):

    @InterceptWith({LoginInterceptor.class, PermissionInterceptor.class})
    public class AdminActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_admin_activity);
    
            ActivityResult activityResult = new ActivityResult(this);
            activityResult.intercept(new OnInterceptResult(this) {
                @Override
                public void invoke() {
                    TextView textView = findViewById(R.id.contentView);
                    textView.setText("This The Admin Manager page");
                }
            });
        }
    }
    

    2. 以挂回调的方式接收activityResult:

    Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.CommonDataKinds.Phone.CONTENT_URI);
    ActivityResult activityResult = new ActivityResult(this);
    activityResult.startActivityForResult(intent, new OnResultCallback() {
    
        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (resultCode == Activity.RESULT_OK) {
                String phoneNum = Util.resolvePhoneNumber(getApplicationContext(), data.getData());
                Toast.makeText(MainActivity.this, "phone number: " + phoneNum, Toast.LENGTH_SHORT).show();
            }
        }
    });
    

    3. 如何实现之ActivityResult:

    public class ActivityResult {
        private static final String TAG = ActivityResult.class.getSimpleName();
    
        private List<Interceptor> mInterceptors = new ArrayList<>();
        private Lazy<ResultFragment> mResultFragment;
    
        public ActivityResult(FragmentActivity activity) {
            mResultFragment = getLazySingleton(activity.getSupportFragmentManager());
            findInterceptors(activity);
        }
    
        public ActivityResult(Fragment fragment) {
            mResultFragment = getLazySingleton(fragment.getChildFragmentManager());
            findInterceptors(fragment);
        }
    
        /**
         * Convenient method to start activity for result.
         */
        public void startActivityForResult(Intent intent, OnResultCallback callback) {
            mResultFragment.get().startActivityForResult(intent, callback);
        }
    
        /**
         * Check if interceptors specified with annotation {@link InterceptWith} are valid or not.
         */
        public void intercept(final OnInterceptResult callback) {
            mResultFragment.get().intercept(new OnResultCallback() {
                @Override
                public void onActivityResult(int requestCode, int resultCode, Intent data) {
                    for (Interceptor interceptor : mInterceptors) {
                        if (interceptor.getRequestCode() == requestCode) {
                            if (resultCode == Activity.RESULT_OK) {
                                verifyInterceptors(callback);
                                break;
                            } else if (resultCode == Activity.RESULT_CANCELED) {
                                callback.finishSelf();
                                break;
                            }
                        }
                    }
                }
            });
    
            // verify interceptors
            if (!mInterceptors.isEmpty()) {
                verifyInterceptors(callback);
            }
        }
    
        private void findInterceptors(Object object) {
            mInterceptors.clear();
            InterceptWith annotation = object.getClass().getAnnotation(InterceptWith.class);
            if (annotation != null) {
                Class<? extends Interceptor>[] classes = annotation.value();
                for (Class<? extends Interceptor> clazz : classes) {
                    try {
                        mInterceptors.add(clazz.newInstance());
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        private void verifyInterceptors(OnInterceptResult callback) {
            if (mInterceptors.isEmpty()) {
                return;
            }
    
            for (int i = 0; i < mInterceptors.size(); i++) {
                Interceptor interceptor = mInterceptors.get(i);
                if (interceptor.isValid(mResultFragment.get().getContext())) {
                    if (i == mInterceptors.size() - 1) {
                        callback.invoke();
                        break;
                    }
                } else {
                    interceptor.process(mResultFragment.get());
                    break;
                }
            }
        }
    
        @NonNull
        private Lazy<ResultFragment> getLazySingleton(@NonNull final FragmentManager fragmentManager) {
            return new Lazy<ResultFragment>() {
                private ResultFragment permissionsFragment;
    
                @Override
                public synchronized ResultFragment get() {
                    if (permissionsFragment == null) {
                        permissionsFragment = getPermissionsFragment(fragmentManager);
                        permissionsFragment.setLogging(true);
                    }
                    return permissionsFragment;
                }
            };
        }
    
        private ResultFragment getPermissionsFragment(@NonNull final FragmentManager fragmentManager) {
            ResultFragment permissionsFragment = (ResultFragment) fragmentManager.findFragmentByTag(TAG);
            boolean isNewInstance = permissionsFragment == null;
            if (isNewInstance) {
                permissionsFragment = new ResultFragment();
                fragmentManager
                        .beginTransaction()
                        .add(permissionsFragment, TAG)
                        .commitNow();
            }
            return permissionsFragment;
        }
    
        @FunctionalInterface
        interface Lazy<V> {
            V get();
        }
    }
    

    两个构造函数使得可以在Activity和Fragment里工作,了解之前文章的朋友会发现解析注解的工作现在放在了ActivityResult里了,不再依赖Override Activity了。ActivityResult的作用就是创建ResultFragment并委托其startActivityForResult(), 随后的结果返回通过OnResultCallback或者OnInterceptResult传递出去。

    4. 如何实现之ResultFragment:

    /**
     * It's a interceptor fragment and it is used to startActivityForResult()
     * and pass activity result to its observer via callback.
     */
    public class ResultFragment extends Fragment {
        private static final String TAG = "PermissionsFragment";
        public static final int REQUEST_CODE = 9998;
    
        private OnResultCallback mOnResultCallback;
        private boolean mLogging;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setRetainInstance(true);
        }
    
        void startActivityForResult(Intent intent, OnResultCallback callback) {
            startActivityForResult(intent, REQUEST_CODE);
            mOnResultCallback = callback;
        }
    
        void intercept(OnResultCallback callback) {
            mOnResultCallback = callback;
        }
    
        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            mOnResultCallback.onActivityResult(requestCode, resultCode, data);
        }
    }
    

    ResultFragment的实现非常简单,它就是一个普通Fragment,负责把activityResult通过callback回传给它的创建者。

    完整实现可以参考这里

    相关文章

      网友评论

        本文标题:打开页面自动登录并回来-拦截器(升级版)

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