Android开发经验谈Android开发Android开发

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

2018-10-27  本文已影响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回传给它的创建者。

完整实现可以参考这里

上一篇下一篇

猜你喜欢

热点阅读