ARouter的路由跳转发生了什么事儿

在组件化的时候,组件与组件是高度解耦的,但组件与组件之间需要通信,这不得不提到ARouter

说在前面

ARouter.png
// Cache route and metas
static Map> groupsIndex = new HashMap<>(); // 添加注解后将映射关系添加到这个集合当中
static Map routes = new HashMap<>(); // 跳转某个路由后的缓存,包括常用的Activity,Framgent,清单文件的meta

// Cache provider
static Map providers = new HashMap<>(); // 实现IProvider的注解后映射关系添加到这个集合中
static Map providersIndex = new HashMap<>(); // IProvider的缓存

// Cache interceptor
static Map> interceptorsIndex = new UniqueKeyTreeMap<>("More than one interceptors use same priority [%s]"); // 实现IInterceptor的注解映射关系添加到这个集合中
static List interceptors = new ArrayList<>(); // IInterceptor的缓存

分析目标

若需要对Activity路由,只需要添加@Route,如

@Route(path = "/test/activity2")

当添加注解后,会通过apt生成ARouter%Group%test的文件,里面包含有需要路由的相关的信息,包含一个RouteType枚举类,如

atlas.put("/test/activity2", RouteMeta.build(RouteType.ACTIVITY, Test2Activity.class, "/test/activity2", "test"));

RouteType是一个枚举,枚举了如下:

ACTIVITY(0, "android.app.Activity"),
SERVICE(1, "android.app.Service"),
PROVIDER(2, "com.alibaba.android.arouter.facade.template.IProvider"),
CONTENT_PROVIDER(-1, "android.app.ContentProvider"),
BOARDCAST(-1, ""),
METHOD(-1, ""),
FRAGMENT(-1, "android.app.Fragment"),
UNKNOWN(-1, "Unknown route type");

常见的有Activity,Fragment,接口实现类IProvider

案例分析

ARouter.init(getApplication())
ARouter.getInstance().build("/test/activity2").navigation();

这两行代码发生了什么事情

首先看init方法

public static void init(Application application) {
    if (!hasInit) {
        hasInit = _ARouter.init(application);
        if (hasInit) {
            _ARouter.afterInit();
        }
    }
}

hasInit默认为false

protected static synchronized boolean init(Application application) {
    mContext = application;
    LogisticsCenter.init(mContext, executor);
    hasInit = true;
    mHandler = new Handler(Looper.getMainLooper());
    return true;
}

public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
    if (registerByPlugin) {
            logger.info(TAG, "Load router map by arouter-auto-register plugin.");
        } else {
            ...
    }
}

我调试发现registerByPlugin = true,只是打印了一个log
这里是将hasInit设置为true,代表初始化成功了,并返回true

接着会调用_ARouter.afterInit() 这里是初始化一个 PROVIDER,仅此而已

这里只是初始化了ARouter.init(getApplication()) 东西并不多

接着会路由跳转,在分析之前,我先阐述下ARouter与_ARouter系,他们的关系是23种设计模式中的外观模式,_ARouter是核心类,基本上所有的逻辑都在这里面,ARouter只是包了一层,做了下方法的传递

ARouter.getInstance().build("/test/activity2")

进入到_ARouter.build()里

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), true);
    }
}

第5行是对path做处理,由于没有添加注解,pService=null,接着调用build()

protected Postcard build(String path, String group, Boolean afterReplace) {
    ...
    return new Postcard(path, group);
}

关键代码只有 return new Postcard(path, group),而Postcard继承的是RouteMeta,build()走完后,调用navigation()

public Object navigation(Context context, NavigationCallback callback) {
    return ARouter.getInstance().navigation(context, this, -1, callback);
}

由于ARouter和_ARouter是外观设计模式,直接看_ARouter的navigation

protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
    PretreatmentService pretreatmentService = ARouter.getInstance().navigation(PretreatmentService.class);
    if (null != pretreatmentService && !pretreatmentService.onPretreatment(context, postcard)) {
        // Pretreatment failed, navigation canceled.
        return null;
    }

    // Set context to postcard.
    postcard.setContext(null == context ? mContext : context);

    try {
        LogisticsCenter.completion(postcard);
    } catch (NoRouteFoundException ex) {
        ...
        return null;
    }

    if (null != callback) {
        callback.onFound(postcard);
    }

    if (!postcard.isGreenChannel()) {   // It must be run in async thread, maybe interceptor cost too mush time made ANR.
        interceptorService.doInterceptions(postcard, new InterceptorCallback() {
            @Override
            public void onContinue(Postcard postcard) {
                _navigation(postcard, requestCode, callback);
            }
            @Override
            public void onInterrupt(Throwable exception) {
                if (null != callback) {
                    callback.onInterrupt(postcard);
                }

                logger.info(Consts.TAG, "Navigation failed, termination by interceptor : " + exception.getMessage());
            }
        });
    } else {
        return _navigation(postcard, requestCode, callback);
    }

    return null;
}

第2,3行代码又是一个拦截,由于没有实现,这里忽略,看第12行代码LogisticsCenter.completion(postcard);

public synchronized static void completion(Postcard postcard) {
    RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
    if (null == routeMeta) {
        // Load route and cache it into memory, then delete from metas.
        addRouteGroupDynamic(postcard.getGroup(), null);

        completion(postcard);   // Reload
    } else {
        postcard.setDestination(routeMeta.getDestination());
        postcard.setType(routeMeta.getType());
        postcard.setPriority(routeMeta.getPriority());
        postcard.setExtra(routeMeta.getExtra());

        switch (routeMeta.getType()) {
            case PROVIDER:  // if the route is provider, should find its instance
                // Its provider, so it must implement IProvider
                Class providerMeta = (Class) routeMeta.getDestination();
                IProvider instance = Warehouse.providers.get(providerMeta);
                if (null == instance) { // There's no instance of this provider
                    IProvider provider;
                    try {
                        provider = providerMeta.getConstructor().newInstance();
                        provider.init(mContext);
                        Warehouse.providers.put(providerMeta, provider);
                        instance = provider;
                    } catch (Exception e) {
                        logger.error(TAG, "Init provider failed!", e);
                        throw new HandlerException("Init provider failed!");
                    }
                }
                postcard.setProvider(instance);
                postcard.greenChannel();    // Provider should skip all of interceptors
                break;
            case FRAGMENT:
                postcard.greenChannel();    // Fragment needn't interceptors
            default:
                break;
        }
    }
}

if 和 else里做的事情是,如果缓存中没有指定的path(第一次调用group),则走if,去解析,else 则做赋值等操作,

public synchronized static void addRouteGroupDynamic(String groupName, IRouteGroup group) {
    if (Warehouse.groupsIndex.containsKey(groupName)){
        Warehouse.groupsIndex.get(groupName).getConstructor().newInstance().loadInto(Warehouse.routes);
        Warehouse.groupsIndex.remove(groupName);
    }

    // cover old group.
    if (null != group) {
        group.loadInto(Warehouse.routes);
    }
}

第3行是通过group在groupsIndex中获取class,groupsIndex是@Route注解后添加到集合的,通过反射获取对象后,将相同的group放到routes集合里,放到routes后再调用completion,则走 else

postcard.setDestination(routeMeta.getDestination());
        postcard.setType(routeMeta.getType());
        postcard.setPriority(routeMeta.getPriority());
        postcard.setExtra(routeMeta.getExtra());

        switch (routeMeta.getType()) {
            case PROVIDER:  // if the route is provider, should find its instance
                // Its provider, so it must implement IProvider
                Class providerMeta = (Class) routeMeta.getDestination();
                IProvider instance = Warehouse.providers.get(providerMeta);
                if (null == instance) { // There's no instance of this provider
                    IProvider provider;
                    try {
                        provider = providerMeta.getConstructor().newInstance();
                        provider.init(mContext);
                        Warehouse.providers.put(providerMeta, provider);
                        instance = provider;
                    } catch (Exception e) {
                        logger.error(TAG, "Init provider failed!", e);
                        throw new HandlerException("Init provider failed!");
                    }
                }
                // 将实例对象放在postcard中
                postcard.setProvider(instance); 
                postcard.greenChannel(); 
                break;
            case FRAGMENT:
                postcard.greenChannel();
            default:
                break;
        }

这里做了一些赋值操作,如果是PROVIDER且providers缓存集合里没有时,通过返回获取实例以后会调用init()方法,并将对象放到providers缓存集合中

至此,Postcard初始化完成

if (!postcard.isGreenChannel()) {   // It must be run in async thread, maybe interceptor cost too mush time made ANR.
        interceptorService.doInterceptions(postcard, new InterceptorCallback() {
            @Override
            public void onContinue(Postcard postcard) {
                _navigation(postcard, requestCode, callback);
            }
            @Override
            public void onInterrupt(Throwable exception) {
                if (null != callback) {
                    callback.onInterrupt(postcard);
                }

                logger.info(Consts.TAG, "Navigation failed, termination by interceptor : " + exception.getMessage());
            }
        });
    } else {
        return _navigation(postcard, requestCode, callback);
    }

这里是调用了拦截器,若注解了拦截器,会先走拦截器里实现的逻辑,在调用onContinue方法的_navigation方法

private Object _navigation(final Postcard postcard, final int requestCode, final NavigationCallback callback) {
    final Context currentContext = postcard.getContext();

    switch (postcard.getType()) {
        case ACTIVITY:
            final Intent intent = new Intent(currentContext, postcard.getDestination());
            intent.putExtras(postcard.getExtras());
            ...
            runInMainThread(new Runnable() {
                @Override
                public void run() {
                    startActivity(requestCode, currentContext, intent, postcard, callback);
                }
            });

            break;
        case PROVIDER:
            return postcard.getProvider();
        case BOARDCAST:
        case CONTENT_PROVIDER:
        case FRAGMENT:
            Class fragmentMeta = postcard.getDestination();
            try {
                Object instance = fragmentMeta.getConstructor().newInstance();
                if (instance instanceof Fragment) {
                    ((Fragment) instance).setArguments(postcard.getExtras());
                } else if (instance instanceof android.support.v4.app.Fragment) {
                    ((android.support.v4.app.Fragment) instance).setArguments(postcard.getExtras());
                }

                return instance;
            } catch (Exception ex) {
                logger.error(Consts.TAG, "Fetch fragment instance error, " + TextUtils.formatStackTrace(ex.getStackTrace()));
            }
        case METHOD:
        case SERVICE:
        default:
            return null;
    }

    return null;
}

若是ACTIVITY,则跳转到activity,
若是PROVIDER,则返回IProvider对象,
若是BOARDCAST,CONTENT_PROVIDER,FRAGMENT,则返回Fragment对象

总结

若是路由的是Activity,则直接跳转到指定的Activity,若是其他的,则获取实例后进行其他逻辑的处理

你可能感兴趣的:(ARouter的路由跳转发生了什么事儿)