美文网首页
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拦截器使用及源码解析(二)

    阿里ARouter的分析计划 阿里ARouter使用及源码解析(一) 阿里ARouter拦截器使用及源码解析(二)...

  • Android之旅 -- ARouter 源码分析(二)

    Android之旅 -- ARouter 源码分析(一) 主要介绍了 ARouter 启动 activity 的基...

  • [Android] ARouter

    开源最佳实践:Android平台页面路由框架ARouter Alibaba-ARouter 源码分析笔记 ARou...

  • ARouter源码解析(二)

    arouter-api version : 1.4.1 前言 前几天对 ARouter 的页面跳转源码进行了分析,...

  • ARouter源码分析

    ARouter源码解读 以前看优秀的开源项目,看到了页面路由框架ARouter,心想页面路由是个啥东东,于是乎网上...

  • ARouter源码分析

    前言 Android app开发中,经常会用到组件化技术,具体表现就是将各个模块以module的方式集成在主模块(...

  • ARouter源码分析

    目录 1.源码思维导图2.运行时源码分析3.编译期原理3.总结 1.ARouter源码思维导图 这个图是最近总结组...

  • Arouter源码分析

    Arouter核心请求类图 Arouter 和 _Arouter 的关系 _Arouter主要是处理Arouter...

  • ARouter源码分析

    前置知识 APT Annotation Processing Tool,自定义注解处理器。搞Android的基本上...

  • ARouter的源码分析

    分析需要储备以下知识点: Java注解知识 Java反射知识 javapoet库(在注释里也有简单分析) auto...

网友评论

      本文标题:ARouter源码分析

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