ARouter源码理解(二)

ARouter中Interceptor原理理解(一)

本文的目的

最近在实践jetpack的Navigation,由于google推荐使用一个activity 其余都是fragment来进行编程,所以打算借鉴阿里巴巴的开源路由框架ARouter打造一个基于Navigation 简化版的ARouter主要为了实现对需要登录信息页面入口的拦截,点击需要登录的页面检查本地token如果没有就先去登录,登陆完后进入目标页面。

带着问题看代码

接着上次对ARouter的这次带着疑问来进一步理解,疑问是:为什么我们能通过 ARouter.getInstance().build(xxx).navigation() 进行Activity的跳转的,ARouter又是如何通过 @Route(path = xxx) 来找到对应的activity的。

简单猜测一下:

ARouter根据 ARouter.getInstance().build(xxx) 传入的path来对比我们Activity类上的@Route方法中的path对应的值在navigation()方法调用的时候来进行匹配找到Activity后再通过startActivity()或者startActivityForResult()

话不多说,从源码的build方法入手

/**
     * Build postcard by path and default group
     */
    protected Postcard build(String path) {
        if (TextUtils.isEmpty(path)) {
            throw new HandlerException(Consts.TAG + "Parameter is invalid!");
        } else {
            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
            if (null != pService) {
                path = pService.forString(path);
            }
            return build(path, extractGroup(path));
        }
    }

PathReplaceService.forString(path)可以先不管,PathReplaceService从字面意思可知是通过我们build传入的字符串进过PathRelaceService处理一下传给build(path,extractGroup(path))这个方法:

/**
     * Build postcard by path and group
     */
    protected Postcard build(String path, String group) {
        if (TextUtils.isEmpty(path) || TextUtils.isEmpty(group)) {
            throw new HandlerException(Consts.TAG + "Parameter is invalid!");
        } else {
            PathReplaceService pService = ARouter.getInstance().navigation(PathReplaceService.class);
            if (null != pService) {
                path = pService.forString(path);
            }
            return new Postcard(path, group);
        }
    }

然后调用PostCard中传入path和group字符串参数的构造函数

	public Postcard(String path, String group) {
        this(path, group, null, null);
    }
	public Postcard(String path, String group, Uri uri, Bundle bundle) {
      	setPath(path);
        setGroup(group);
        setUri(uri);
        this.mBundle = (null == bundle ? new Bundle() : bundle);
    }

PostCard是RouteMeta类的子类,Path和Gourp是RouteMeta的成员变量,
Bundle和Uri则是PostCard的成员变量

public class RouteMeta {
    private RouteType type;         // Type of route
    private Element rawType;        // Raw type of route
    private Class<?> destination;   // Destination
    private String path;            // Path of route
    private String group;           // Group of route
    private int priority = -1;      // The smaller the number, the higher the priority
    private int extra;              // Extra data
    private Map<String, Integer> paramsType;  // Param type
    private String name;
    
public final class Postcard extends RouteMeta {
    // Base
    private Uri uri;
    private Object tag;             // A tag prepare for some thing wrong.
    private Bundle mBundle;   

PostCard中有多个navigation方法,

 /**
     * Navigation to the route with path in postcard.
     * No param, will be use application context.
     */
    public Object navigation() {
        return navigation(null);
    }

    /**
     * Navigation to the route with path in postcard.
     *
     * @param context Activity and so on.
     */
    public Object navigation(Context context) {
        return navigation(context, null);
    }

    /**
     * Navigation to the route with path in postcard.
     *
     * @param context Activity and so on.
     */
    public Object navigation(Context context, NavigationCallback callback) {
        return ARouter.getInstance().navigation(context, this, -1, callback);
    }

我们最常调用的

ARouter.getInstance().build(xxx).navigation()
等于Postcard postcard = ARouter.getInstance().build(xxx)
postcard.navigation()

无参的postcard.navigation()实际调用的postcard.navigation(null,null)等于
ARouter.getInstance().navigation(null,this,-1,null)由前文可知ARouter用了门面模式实际执行者是_ARouter类,

/**
     * Launch the navigation.
     *
     * @param mContext    .
     * @param postcard    .
     * @param requestCode Set for startActivityForResult
     * @param callback    cb
     */
    public Object navigation(Context mContext, Postcard postcard, int requestCode, NavigationCallback callback) {
        return _ARouter.getInstance().navigation(mContext, postcard, requestCode, callback);
    }

先跳过参数处理和拦截器部分的源码,_ARouter里真正执行的是_navigation(context, postcard, requestCode, callback);
看我们最熟悉的Activity的部分:

switch (postcard.getType()) {
            case ACTIVITY:
                // Build intent
                final Intent intent = new Intent(currentContext, postcard.getDestination());
                intent.putExtras(postcard.getExtras());

                // Set flags.
                int flags = postcard.getFlags();
                if (-1 != flags) {
                    intent.setFlags(flags);
                } else if (!(currentContext instanceof Activity)) {    // Non activity, need less one flag.
                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                }

                // Set Actions
                String action = postcard.getAction();
                if (!TextUtils.isEmpty(action)) {
                    intent.setAction(action);
                }

                // Navigation in main looper.
                runInMainThread(new Runnable() {
                    @Override
                    public void run() {
                        startActivity(requestCode, currentContext, intent, postcard, callback);
                    }
                });

                break;

代码几乎无难度,和源码有出入的地方在 startActivity(requestCode, currentContext, intent, postcard, callback);这个方法

/**
     * Start activity
     *
     * @see ActivityCompat
     */
    private void startActivity(int requestCode, Context currentContext, Intent intent, Postcard postcard, NavigationCallback callback) {
        if (requestCode >= 0) {  // Need start for result
            if (currentContext instanceof Activity) {
                ActivityCompat.startActivityForResult((Activity) currentContext, intent, requestCode, postcard.getOptionsBundle());
            } else {
                logger.warning(Consts.TAG, "Must use [navigation(activity, ...)] to support [startActivityForResult]");
            }
        } else {
            ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle());
        }

        if ((-1 != postcard.getEnterAnim() && -1 != postcard.getExitAnim()) && currentContext instanceof Activity) {    // Old version.
            ((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim());
        }

        if (null != callback) { // Navigation over.
            callback.onArrival(postcard);
        }
    }

结合PostCard中的注解可知是对动画进行处理的逻辑

// Animation
private Bundle optionsCompat; // The transition animation of activity

你可能感兴趣的:(知识点归纳)