Arouter源码分析之初始化

Arouter跟Butterknife一样,都是采用APT技术,在编译时生成一些对应的文件。

Arouter的初始化是在Application的onCreate()进行

ARouter # init()
 ARouter.init(this);
public static void init(Application application) {
        if (!hasInit) {
            logger = _ARouter.logger;
            _ARouter.logger.info(Consts.TAG, "ARouter init start.");
            hasInit = _ARouter.init(application);//分析1

            if (hasInit) {
                _ARouter.afterInit();//分析2
            }

            _ARouter.logger.info(Consts.TAG, "ARouter init over.");
        }
    }

刚开始进去是还没有初始化的,所以会走

_ARouter # init()
hasInit = _ARouter.init(application);

可以看到是调用_ARouter的init(),进入该方法:

protected static synchronized boolean init(Application application) {
        mContext = application;
        LogisticsCenter.init(mContext, executor);//1
        logger.info(Consts.TAG, "ARouter init success!");
        hasInit = true;
        mHandler = new Handler(Looper.getMainLooper());

        return true;
    }

在这个方法里面主要是将hasInit置为true.然后创建一个主线程的Handler。此处调用了 LogisticsCenter.init(),主要分析此处。

LogisticsCenter # init()
public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
        mContext = context;
        executor = tpe;

        try {
            long startInit = System.currentTimeMillis();
            loadRouterMap();
            if (registerByPlugin) {
                logger.info(TAG, "Load router map by arouter-auto-register plugin.");
            } else {
                Set routerMap;

                // It will rebuild router map every times when debuggable.
                if (ARouter.debuggable() || PackageUtils.isNewVersion(context)) {
                    logger.info(TAG, "Run with debug mode or new install, rebuild router map.");
                    // These class was generated by arouter-compiler.
                    routerMap = ClassUtils.getFileNameByPackageName(mContext, ROUTE_ROOT_PAKCAGE);
                    if (!routerMap.isEmpty()) {
                        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 {
                    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()));
                }

                logger.info(TAG, "Find router map finished, map size = " + routerMap.size() + ", cost " + (System.currentTimeMillis() - startInit) + " ms.");
                startInit = System.currentTimeMillis();

                for (String className : routerMap) {
                    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);
                    } else if (className.startsWith(ROUTE_ROOT_PAKCAGE + DOT + SDK_NAME + SEPARATOR + SUFFIX_INTERCEPTORS)) {
                        // Load interceptorMeta
                        ((IInterceptorGroup) (Class.forName(className).getConstructor().newInstance())).loadInto(Warehouse.interceptorsIndex);
                    } 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() + "]");
        }
    }

这个方法的主要的作用是加载所有的内存中的metas,数据初始化。

首先调用loadRouterMap(),这个方法就是将registerByPlugin变量置为false.

当registerByPlugin为false时,会走else的逻辑。

先创建一个Set集合,当是debug状态下或者App升级版本,那么routerMap中存储的值就需要重新获取。然后通过包名拿到该包下的所有className.

ROUTE_ROOT_PAKCAGE 对应着 com.alibaba.android.arouter.routes

在编译期间 ARouter会使用APT技术,使用注解处理器扫描module中的注解,在process方法中成相应的代码文件

生成的代码文件就放在com.alibaba.android.arouter.routes该包下

拿到之后,用SharedPreferences进行缓存。

然后循环遍历拿到的ClassName,拿到包下类的ClassName后,进行分类,通过反射拿到相应类的实例,调用loadInto方法,将数据存储到数据仓库(WarseHouse)中的集合中.

你可能感兴趣的:(Arouter源码分析之初始化)