美文网首页
ARouter源码分析

ARouter源码分析

作者: gogoingmonkey | 来源:发表于2021-05-19 10:28 被阅读0次

    目录

    1.源码思维导图
    2.运行时源码分析
    3.编译期原理
    3.总结

    1.ARouter源码思维导图

    这个图是最近总结组件化时扣出来的!


    image.png

    2.ARouter源码分析

    1.init阶段

    我们找到Arouter的入口,也就是初始化的地方:

    if (isDebug()) {           // 这两行必须写在init之前,否则这些配置在init过程中将无效
        ARouter.openLog();     // 打印日志
        ARouter.openDebug();   // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
    }
    ARouter.init(mApplication); // 尽可能早,推荐在Application中初始化
    

    我们直接看ARouter.init方法

        /**
         * Init, it must be call before used router.
         */
        public static void init(Application application) {
            if (!hasInit) { //确保只初始化一次
                logger = _ARouter.logger;//日志类
                _ARouter.logger.info(Consts.TAG, "ARouter init start.");
                hasInit = _ARouter.init(application);
    
                if (hasInit) {
                    _ARouter.afterInit();
                }
    
                _ARouter.logger.info(Consts.TAG, "ARouter init over.");
            }
        }
    

    接着我们进入实现类看下: 继续看 _ARouter.java 实现

        protected static synchronized boolean init(Application application) {
            mContext = application;
            LogisticsCenter.init(mContext, executor); // 实际初始化的地方
            logger.info(Consts.TAG, "ARouter init success!");
            hasInit = true;
            return true;
        }
    

    我们只关注重点,LogisticsCenter.init(mContext, executor);,executor是一个线程池。
    主要实现都在 LogisticsCenter.init 方法 中, 继续查看

    public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
        mContext = context;
        executor = tpe;
        ...
        
        Set<String> routerMap;//生成类的类名集合
        // 如果是debug模式或者是新版本,从apt生成的包中加载类
        if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
            // ClassUtils.getFileNameByPackageName 就是根据报名查找对应报名下的类, 就不贴代码了..
            routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
            if (!routerMap.isEmpty()) {//加入sp缓存
                context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).edit().putStringSet(AROUTER_SP_KEY_MAP, routerMap).apply();
            }
    
            PackageUtils.updateVersion(context); //更新版本
        } else {//否则从缓存读取类名
            routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
        }
        
        //判断类型,使用反射实例化对象,并调用方法       // 遍历获取到的 class
        for (String className : routerMap) {
            if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
                ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
            } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
                ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
            } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
                ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
            }
    
    `ROUTE_ROOT_PAKCAGE`是一个常量:
    
    ```java
    public static final String ROUTE_ROOT_PAKCAGE = "com.alibaba.android.arouter.routes";
    

    ClassUtils.getFileNameByPackageName方法做的就是找到app的dex,然后遍历出其中的属于com.alibaba.android.arouter.routes包下的所有类名,打包成集合返回。可以想象遍历整个dex查找指定类名的工作量有多大,怎么办呢?就需要[arouter-gradle-plugin] ASM插桩来解决这个非常耗费性能问题

    可以看到初始化就是查找com.alibaba.android.arouter.routes包下的类, 获取实例并强制转化成IRouteRoot, IInterceptorGroup, IProviderGroup, 然后调用 loadInto 方法.

    通过 demo 的代码查找能看到有
    com.alibaba.android.arouter.routes.ARouter$$Root$$app这样的类

    // ARouter$$Root$$app.java
    /**
     * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
    public class ARouter$$Root$$app implements IRouteRoot {
        public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
            // 以分组做为 key, 缓存到 routes. 
            // routes 是指向 Warehouse.groupsIndex 的引用
            routes.put("service", ARouter$$Group$$service.class);
            routes.put("test", ARouter$$Group$$test.class);
        }
    }
    

    可以看到这是在编译期通过分析注解生成的代码.ARouter$$Group$$service.class也是生成.

    // ARouter$$Group$$service.java
    /**
     * DO NOT EDIT THIS FILE!!! IT WAS GENERATED BY AROUTER. */
    public class ARouter$$Group$$service implements IRouteGroup {
        @Override
        public void loadInto(Map<String, RouteMeta> atlas) {
            atlas.put("/service/hello", RouteMeta.build(RouteType.PROVIDER, HelloServiceImpl.class, "/service/hello", "service", null, -1, -2147483648));
            ...
        }
    }
    

    到这里可以看到demo代码里定义的HelloServiceImpl.java 等出现了. 其实 ARouter 就是通过分析注解在编译期自动生成了一些关联代码. 另外的 Interceptors, Providers 逻辑上类似.
    Interceptors 是注册了声明 Interceptor 注解, 并实现 IInterceptor 接口的类, Providers 是注册了声明 Route 注解, 并实现了 IProvider 接口的类

    init流程总结:

    初始化工作都做完了, 总结一下 ARouter 会在编译期根据注解声明分析自动生成一些注入代码, 初始化工作主要是把这些注解的对象和对注解的配置缓存到 Warehouse 的静态对象中.

    2.跳转

    // 跳转activity的调用
    ARouter.getInstance().build("/test/activity2").navigation();
    
    // ARouter.java 
    public Postcard build(String path) {
        return _ARouter.getInstance().build(path);
    }
    
    // _ARouter.java
    // group 默认是传进来的 path 第一部分内容. 例如 path = /test/activity1, group会默认为 test
    // 如果手动声明的,一定要手动传递, 不然会找不到
    protected Postcard build(String path, String group) {
        return new Postcard(path, group);
    }
    

    这里就是直接返回了一个 Postcard 对象, 并保存了path, group. Postcard 是继承了 RouteMeta
    navigation方法最后都要调用的 _ARouter.java 中, 中间过程省略.我们直接看核心代码

    // _ARouter.java
    // postcard 就是前面用build 方法构造的对象实例
    // requestCode 是区分 startAcitivity 的方式.如果不为-1, 就用startActivityForResult的方式启动
    // NavigationCallback 是对各种状态的回调. 
    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        try {
            // 验证是否能找到对应的 postcard.path
            LogisticsCenter.completion(postcard);
        } catch (NoRouteFoundException ex) {
            // 如果没找到postcard的配置, 调用onLost回调方法, 或者系统配置的"降级服务"(DegradeService)回调
            if (null != callback) {
                callback.onLost(postcard);
            } else {    
                DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
                if (null != degradeService) {
                    degradeService.onLost(context, postcard);
                }
            }
            return null;
        }
    
        ... 
     }
    

    navigation调用了LogisticsCenter.completion方法做验证, 我们看下 LogisticsCenter.java 这个方法如何验证 postcard, 然后再继续看navigation方法下面的逻辑

    // LogisticsCenter.java
    public synchronized static void completion(Postcard postcard) {
        // 通过postcard 的 path 查找对应的 RouteMeta
        RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
    
        if (null == routeMeta) {
            // 如果没找到, 可能是还没装载过, 需要根据 group 查找对应的 groups
            Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup()); 
            if (null == groupMeta) {
                // 如果没找到, 抛出 NoRouteFoundException 错误方法结束
                throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
    
            } else {
                // 返回 IRouteGroup 对象, 并调用 loadInto方法.
                IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
                iGroupInstance.loadInto(Warehouse.routes);
    
                // 删除 group 缓存
                Warehouse.groupsIndex.remove(postcard.getGroup());
    
                // 重新调用 completion 方法,此时对应的 group 已经缓存完成
                completion(postcard);   // Reload
            }
    
        } else {
            // 可以查找到 routeMeta, copy routeMeta 的原始数据到 postcard 中.
            postcard.setDestination(routeMeta.getDestination());
            postcard.setType(routeMeta.getType());
            postcard.setPriority(routeMeta.getPriority());
            postcard.setExtra(routeMeta.getExtra());
    
            switch (routeMeta.getType()) {
            case PROVIDER: 
                Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
                IProvider instance = Warehouse.providers.get(providerMeta);
    
                // 初始化 provider 对象, 并调用初始化方法, 缓存到Warehouse.providers中.
                if (null == instance) {
                    IProvider provider;
                    try {
                        provider = providerMeta.getConstructor().newInstance();
                        provider.init(mContext);
                        Warehouse.providers.put(providerMeta, provider);
                        instance = provider;
                    } catch (Exception e) {
                        throw new HandlerException("Init provider failed! " + e.getMessage());
                    }
                }
                
                // 设置一个provider 引用
                postcard.setProvider(instance);
    
                // provider 默认设置跳过拦截器
                postcard.greenChannel(); 
                break;
            case FRAGMENT:
                // fragment 默认设置跳过拦截器
                postcard.greenChannel(); 
            default:
                break;
            }
        }
    }
    

    completion方法主要是对 group 做一次懒式加载, 我们继续查看 navigation 方法下面的内容:

    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        ...
    
        // 执行到这里就是找到了 postcard. 执行对应回调
        if (null != callback) {
            callback.onFound(postcard);
        }
    
        // 如果是"绿色通道", 则直接执行_navigation方法, 目前只有provider, fragment 默认是走绿色通道
        if (!postcard.isGreenChannel()) { 
            // interceptorService 是 ARouter 配置的默认的拦截服务
            interceptorService.doInterceptions(postcard, new InterceptorCallback() {
    
                public void onContinue(Postcard postcard) {
                    _navigation(context, postcard, requestCode, callback);
                }
    
                public void onInterrupt(Throwable exception) {
                    if (null != callback) {
                        callback.onInterrupt(postcard);
                    }
                }
            });
        } else {
            // 绿色通道
            return _navigation(context, postcard, requestCode, callback);
        }
        return null;
     }
    

    interceptorService 是 ARouter 配置的默认的拦截器com.alibaba.android.arouter.core.InterceptorServiceImpl.java

    public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
        // 用线程池异步执行
        LogisticsCenter.executor.execute(new Runnable() {
            public void run() {
                // 初始化一个同步计数类, 用拦截器的 size
                CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size());
                try {
                    // 执行拦截操作, 看到这猜是递归调用.直到 index 满足条件, 退出递归.
                    _excute(0, interceptorCounter, postcard);
                
                    // 线程等待计数完成, 等待300秒...
                    interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);
    
                    // 判断退出等待后的一些状态...
                    if (interceptorCounter.getCount() > 0) { 
                        callback.onInterrupt(new HandlerException("The interceptor processing timed out."));
                    } else if (null != postcard.getTag()) { 
                        callback.onInterrupt(new HandlerException(postcard.getTag().toString()));
                    } else {
    
                        // 没有问题, 继续执行
                        callback.onContinue(postcard);
                    }
                } catch (Exception e) {
    
                    // 中断
                    callback.onInterrupt(e);
                }
            }
        });
    }
    

    我们继续看看_excute方法

    private static void _excute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) {
        // 递归退出条件
        if (index < Warehouse.interceptors.size()) {
            // 获取要执行的拦截器
            IInterceptor iInterceptor = Warehouse.interceptors.get(index);
    
            // 执行拦截
            iInterceptor.process(postcard, new InterceptorCallback() {
    
                public void onContinue(Postcard postcard) {
                    // 计数器减1
                    counter.countDown();
                    
                    // 继续执行下一个拦截
                    _excute(index + 1, counter, postcard);  
                }
    
                public void onInterrupt(Throwable exception) {
                    // 当被拦截后退出递归
                    postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage()); 
                    counter.cancel();
                }
            });
        }
    }
    

    和我们猜测的一样, 一个标准的递归调用, 当所有拦截器执行后(假设都不做拦截), 最后还是要回到_navigation方法

    private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        final Context currentContext = null == context ? mContext : context;
    
        // 我们就先只分析 activity 的逻辑
        switch (postcard.getType()) {
        case ACTIVITY:
            // 初始化 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)) { 
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
    
             // 在 UI 线程进行 start activity
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                public void run() {
                    if (requestCode > 0) {  // Need start for result
                        ActivityCompat.startActivityForResult((Activity) currentContext, intent, requestCode, postcard.getOptionsBundle());
                    } else {
                        ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle());
                    }
    
                    // 动画设置
                    if ((0 != postcard.getEnterAnim() || 0 != postcard.getExitAnim()) && currentContext instanceof Activity) {    // Old version.
                        ((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim());
                    }
    
                    if (null != callback) { // Navigation over.
                        callback.onArrival(postcard);
                    }
                }
            });
            break;
        }
        return null;
    }
    ``````java
    // 跳转activity的调用
    ARouter.getInstance().build("/test/activity2").navigation();
    
    // ARouter.java 
    public Postcard build(String path) {
        return _ARouter.getInstance().build(path);
    }
    
    // _ARouter.java
    // group 默认是传进来的 path 第一部分内容. 例如 path = /test/activity1, group会默认为 test
    // 如果手动声明的,一定要手动传递, 不然会找不到
    protected Postcard build(String path, String group) {
        return new Postcard(path, group);
    }
    

    这里就是直接返回了一个 Postcard 对象, 并保存了path, group. Postcard 是继承了 RouteMeta
    navigation方法最后都要调用的 _ARouter.java 中, 中间过程省略.我们直接看核心代码

    // _ARouter.java
    // postcard 就是前面用build 方法构造的对象实例
    // requestCode 是区分 startAcitivity 的方式.如果不为-1, 就用startActivityForResult的方式启动
    // NavigationCallback 是对各种状态的回调. 
    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        try {
            // 验证是否能找到对应的 postcard.path
            LogisticsCenter.completion(postcard);
        } catch (NoRouteFoundException ex) {
            // 如果没找到postcard的配置, 调用onLost回调方法, 或者系统配置的"降级服务"(DegradeService)回调
            if (null != callback) {
                callback.onLost(postcard);
            } else {    
                DegradeService degradeService = ARouter.getInstance().navigation(DegradeService.class);
                if (null != degradeService) {
                    degradeService.onLost(context, postcard);
                }
            }
            return null;
        }
    
        ... 
     }
    

    navigation调用了LogisticsCenter.completion方法做验证, 我们看下 LogisticsCenter.java 这个方法如何验证 postcard, 然后再继续看navigation方法下面的逻辑

    // LogisticsCenter.java
    public synchronized static void completion(Postcard postcard) {
        // 通过postcard 的 path 查找对应的 RouteMeta
        RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
    
        if (null == routeMeta) {
            // 如果没找到, 可能是还没装载过, 需要根据 group 查找对应的 groups
            Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup()); 
            if (null == groupMeta) {
                // 如果没找到, 抛出 NoRouteFoundException 错误方法结束
                throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
    
            } else {
                // 返回 IRouteGroup 对象, 并调用 loadInto方法.
                IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
                iGroupInstance.loadInto(Warehouse.routes);
    
                // 删除 group 缓存
                Warehouse.groupsIndex.remove(postcard.getGroup());
    
                // 重新调用 completion 方法,此时对应的 group 已经缓存完成
                completion(postcard);   // Reload
            }
    
        } else {
            // 可以查找到 routeMeta, copy routeMeta 的原始数据到 postcard 中.
            postcard.setDestination(routeMeta.getDestination());
            postcard.setType(routeMeta.getType());
            postcard.setPriority(routeMeta.getPriority());
            postcard.setExtra(routeMeta.getExtra());
    
            switch (routeMeta.getType()) {
            case PROVIDER: 
                Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
                IProvider instance = Warehouse.providers.get(providerMeta);
    
                // 初始化 provider 对象, 并调用初始化方法, 缓存到Warehouse.providers中.
                if (null == instance) {
                    IProvider provider;
                    try {
                        provider = providerMeta.getConstructor().newInstance();
                        provider.init(mContext);
                        Warehouse.providers.put(providerMeta, provider);
                        instance = provider;
                    } catch (Exception e) {
                        throw new HandlerException("Init provider failed! " + e.getMessage());
                    }
                }
                
                // 设置一个provider 引用
                postcard.setProvider(instance);
    
                // provider 默认设置跳过拦截器
                postcard.greenChannel(); 
                break;
            case FRAGMENT:
                // fragment 默认设置跳过拦截器
                postcard.greenChannel(); 
            default:
                break;
            }
        }
    }
    

    completion方法主要是对 group 做一次懒式加载, 我们继续查看 navigation 方法下面的内容:

    protected Object navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        ...
    
        // 执行到这里就是找到了 postcard. 执行对应回调
        if (null != callback) {
            callback.onFound(postcard);
        }
    
        // 如果是"绿色通道", 则直接执行_navigation方法, 目前只有provider, fragment 默认是走绿色通道
        if (!postcard.isGreenChannel()) { 
            // interceptorService 是 ARouter 配置的默认的拦截服务
            interceptorService.doInterceptions(postcard, new InterceptorCallback() {
    
                public void onContinue(Postcard postcard) {
                    _navigation(context, postcard, requestCode, callback);
                }
    
                public void onInterrupt(Throwable exception) {
                    if (null != callback) {
                        callback.onInterrupt(postcard);
                    }
                }
            });
        } else {
            // 绿色通道
            return _navigation(context, postcard, requestCode, callback);
        }
        return null;
     }
    

    interceptorService 是 ARouter 配置的默认的拦截器com.alibaba.android.arouter.core.InterceptorServiceImpl.java

    public void doInterceptions(final Postcard postcard, final InterceptorCallback callback) {
        // 用线程池异步执行
        LogisticsCenter.executor.execute(new Runnable() {
            public void run() {
                // 初始化一个同步计数类, 用拦截器的 size
                CancelableCountDownLatch interceptorCounter = new CancelableCountDownLatch(Warehouse.interceptors.size());
                try {
                    // 执行拦截操作, 看到这猜是递归调用.直到 index 满足条件, 退出递归.
                    _excute(0, interceptorCounter, postcard);
                
                    // 线程等待计数完成, 等待300秒...
                    interceptorCounter.await(postcard.getTimeout(), TimeUnit.SECONDS);
    
                    // 判断退出等待后的一些状态...
                    if (interceptorCounter.getCount() > 0) { 
                        callback.onInterrupt(new HandlerException("The interceptor processing timed out."));
                    } else if (null != postcard.getTag()) { 
                        callback.onInterrupt(new HandlerException(postcard.getTag().toString()));
                    } else {
    
                        // 没有问题, 继续执行
                        callback.onContinue(postcard);
                    }
                } catch (Exception e) {
    
                    // 中断
                    callback.onInterrupt(e);
                }
            }
        });
    }
    

    我们继续看看_excute方法

    private static void _excute(final int index, final CancelableCountDownLatch counter, final Postcard postcard) {
        // 递归退出条件
        if (index < Warehouse.interceptors.size()) {
            // 获取要执行的拦截器
            IInterceptor iInterceptor = Warehouse.interceptors.get(index);
    
            // 执行拦截
            iInterceptor.process(postcard, new InterceptorCallback() {
    
                public void onContinue(Postcard postcard) {
                    // 计数器减1
                    counter.countDown();
                    
                    // 继续执行下一个拦截
                    _excute(index + 1, counter, postcard);  
                }
    
                public void onInterrupt(Throwable exception) {
                    // 当被拦截后退出递归
                    postcard.setTag(null == exception ? new HandlerException("No message.") : exception.getMessage()); 
                    counter.cancel();
                }
            });
        }
    }
    

    和我们猜测的一样, 一个标准的递归调用, 当所有拦截器执行后(假设都不做拦截), 最后还是要回到_navigation方法

    private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
        final Context currentContext = null == context ? mContext : context;
    
        // 我们就先只分析 activity 的逻辑
        switch (postcard.getType()) {
        case ACTIVITY:
            // 初始化 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)) { 
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            }
    
             // 在 UI 线程进行 start activity
            new Handler(Looper.getMainLooper()).post(new Runnable() {
                public void run() {
                    if (requestCode > 0) {  // Need start for result
                        ActivityCompat.startActivityForResult((Activity) currentContext, intent, requestCode, postcard.getOptionsBundle());
                    } else {
                        ActivityCompat.startActivity(currentContext, intent, postcard.getOptionsBundle());
                    }
    
                    // 动画设置
                    if ((0 != postcard.getEnterAnim() || 0 != postcard.getExitAnim()) && currentContext instanceof Activity) {    // Old version.
                        ((Activity) currentContext).overridePendingTransition(postcard.getEnterAnim(), postcard.getExitAnim());
                    }
    
                    if (null != callback) { // Navigation over.
                        callback.onArrival(postcard);
                    }
                }
            });
            break;
        }
        return null;
    }
    
    3.对 IProvider 进行 navigation

    主要实现是在LogisticsCenter.completion方法中对IProvider进行了一些分支处理

            switch (routeMeta.getType()) {
            case PROVIDER: 
                // 返回实现IProvider接口的类
                Class<? extends IProvider> providerMeta = (Class<? extends IProvider>) routeMeta.getDestination();
    
                // 在缓存中查找
                IProvider instance = Warehouse.providers.get(providerMeta);
    
                // 初始化 provider 对象, 并调用初始化方法, 缓存到Warehouse.providers中.
                if (null == instance) {
                    IProvider provider;
                    try {
                        provider = providerMeta.getConstructor().newInstance();
                        provider.init(mContext);
                        Warehouse.providers.put(providerMeta, provider);
                        instance = provider;
                    } catch (Exception e) {
                        throw new HandlerException("Init provider failed! " + e.getMessage());
                    }
                }
                
                // 设置一个provider 引用
                postcard.setProvider(instance);
    
                // provider 默认设置跳过拦截器
                postcard.greenChannel(); 
                break;
    
        // 可以看 _navigation 方法就是直接返回在 completion 方法中是设置的引用
        private Object _navigation(final Context context, final Postcard postcard, final int requestCode, final NavigationCallback callback) {
            final Context currentContext = null == context ? mContext : context;
    
            switch (postcard.getType()) {
    
                case PROVIDER:
                    return postcard.getProvider();
      
            }
    
            return null;
        }
    
    初始化的时候把注解标示的内容注入到缓存中, 然后启动跳转的时候根据缓存查找对应的类的实现. 看上去也是挺简单的,

    3.编译器总结

    ARouter 总结

    我们已经底 ARouter 大部分代码都进行了一遍分析, 接下来总结一下 ARouter 工作原理.

    编译期 arouter-compiler 负责生成了注入的的一些代码:

    - ARouter$$Group$$group-name 以 group-name 为文件名注入该 group 下声明了 @Route 的信息
    - ARouter$$Root$$app 按照 group 分组注入了 ARouter$$Group$$group-name
    - ARouter$$Providers$$app 注入实现 IProvider 接口的信息
    - ARouter$$Interceptors$$app 注入实现 IInterceptor 接口信息
    - Test1Activity$$ARouter$$Autowired @Autowired 自动注入的实现
    

    ARouter 初始化的时候会把注入的信息进行缓存

    在进行 navigation 的时候, 根据缓存进行懒加载, 然后获取实际对象或者跳转 activity.

    自动注入就是调用 对应的 Test1ActivityARouterAutowired 实例, 对声明 @Autowired 的字段进行复制操作.

    相关文章

      网友评论

          本文标题:ARouter源码分析

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