美文网首页
ARouter源码分析-初始化

ARouter源码分析-初始化

作者: dashingqi | 来源:发表于2020-07-16 23:21 被阅读0次
    Android_Banner.jpg

    简介

    • ARouter的初始化很简单,在Application的onCreate()中,一行代码就可以
    ARouter.init(this)
    
    • 看似简单的一行代码,其实背后也为我们做了不少工作,解下来就打开ARouter的源码大门,让我们一探究竟

    初始化源码分析

    ARouter # init()
    ARouter.init(this)
    // 此处调用了ARouter的init方法,让我们看下 init()方法
    
    public static void init(Application application) {
            //判断是否进行过初始化操作
            if (!hasInit) {
            
                logger = _ARouter.logger;
                _ARouter.logger.info(Consts.TAG, "ARouter init start.");
                // ----> 分析1
                hasInit = _ARouter.init(application);
    
                if (hasInit) {
                    _ARouter.afterInit();
                }
    
                _ARouter.logger.info(Consts.TAG, "ARouter init over.");
            }
        }
    
    • 分析1:我们看到,如果ARouter没有进行过初始化操作,就调用了_ARouter.init()
    _ARouter # init()
    protected static synchronized boolean init(Application application) {
            mContext = application;
            // ----> 分析1
            LogisticsCenter.init(mContext, executor);
            //打印日志,ARouter初始化成功,看来上面的一行代码很重要啊
            logger.info(Consts.TAG, "ARouter init success!");
            // ARouter是否初始化的标志设置为true
            hasInit = true;
            mHandler = new Handler(Looper.getMainLooper());
            
            return true;
        }
    
    • 分析1:此处调用了 LogisticsCenter.init(),字面意思LogisticsCenter就是物流中心,该类应该起到承上启下的作用把,我们看下它
    LogisticsCenter # init()
    //该方法接受两个参数 上下文和一个线程池
    public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
            mContext = context;
            executor = tpe;
    
            try {
                long startInit = System.currentTimeMillis();
                ----> 分析1
                loadRouterMap();
                if (registerByPlugin) {
                    logger.info(TAG, "Load router map by arouter-auto-register plugin.");
                } else {
                    Set<String> routerMap;
    
                    // 如果时debug模式,或者App升级版本了,那么routerMap中存储的值就需要重新获取了
                    if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
                        logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
                       // ROUTE_ROOT_PAKCAGE 对应着 com.alibaba.android.arouter.routes 
                       // 在编译期间 ARouter会使用APT技术,使用注解处理器扫描module中的注解,在process方法中生成相应的代码文件
                       // 生成的代码文件就放在com.alibaba.android.arouter.routes该包下
                       // ClassUtils.getFileNameByPackageName() 该方面就是根据提供的包,拿到该包下的ClassName
                        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);    // Save new version name when router map update finishes.
                    } else {
                        // 否则的话就从sp拿到之前的缓存,赋值给routerMap
                        logger.info(TAG, "Load router map from cache.");
                        routerMap = new HashSet<>(context.getSharedPreferences(AROUTER_SP_CACHE_KEY, Context.MODE_PRIVATE).getStringSet(AROUTER_SP_KEY_MAP, new HashSet<String>()));
                    }
    
                    logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms.");
                    startInit = System.currentTimeMillis();
                    // 循环遍历拿到的ClassName
                    for (String className : routerMap) {
                    //如果className是 com.alibaba.android.arouter.routes包下 以 Arouter$$Root开头的话
                        if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_ROOT)) {
                            // This one of root elements, load root.
                            ((IRouteRoot) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.groupsIndex);
                        } 
                        // 如果ClassName 是com.alibaba.android.arouter.routes包下 以 ARouter$$Interceptors开头的
                        else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
                            // Load interceptorMeta
                            ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
                        }
                        // 如果ClassName 是com.alibaba.android.arouter.routes包下 以ARouter$$Providers开头的
                        else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_PROVIDERS)) {
                            // Load providerIndex
                            ((IProviderGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.providersIndex);
                        }
                    }
                }
    
                logger.info(TAG, "Load root element finished, cost " + (System.currentTimeMillis() - startInit) + " ms.");
    
                if (Warehouse.groupsIndex.size() == 0) {
                    logger.error(TAG, "No mapping files were found, check your configuration please!");
                }
    
                if (ARouter.debuggable()) {
                    logger.debug(TAG, String.format(Locale.getDefault(), "LogisticsCenter has already been loaded, GroupIndex[%d], InterceptorIndex[%d], ProviderIndex[%d]", Warehouse.groupsIndex.size(), Warehouse.interceptorsIndex.size(), Warehouse.providersIndex.size()));
                }
            } catch (Exception e) {
                throw new HandlerException(TAG + "ARouter init logistics center exception! [" + e.getMessage() + "]");
            }
        }
    

    总结

    • ARouter的初始化就是拿到com.alibaba.android.arouter.routes包下类的ClassName,该包下的类都是在编译期间使用注解处理器生成的。有 Group、Root、Provider、Interceptor类型的。
    • 拿到包下类的ClassName后,进行分类,通过反射拿到相应类的实例,调用loadInto方法,将数据存储到数据仓库(WarseHouse)中的集合中
    • 这里面仅仅会初始化存储 一级路径与路由地址清单类的映射关系,一级 Provider和Interceptor类型的。至于每组对应的路由清单文件类,会在第一次页面跳转的时候,找到对应组下的路由清单进行初始化。

    相关文章

      网友评论

          本文标题:ARouter源码分析-初始化

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