ARouter源码分析(四)—— 缓存与优化

Arouter源码分析系列建议从最初开始阅读,全部文章请访问https://github.com/AlexMahao/ARouter

本篇博客意在记录ARouter中的一些优秀策略。

辅助类加载机制

ARouter在实现基本功能时,使用apt在指定包名下生成了一些辅助类。辅助类的查询逻辑如下。

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.
                    // 获取com.alibaba.android.arouter.routes的类列表,及Processor生成的辅助类
                    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<String>()));
                }

判断是否是debug或者是否是新版本,其中一个成立,则重新查询并且遍历一下指定包下的所有辅助类。并且将辅助类的全路径保存到sp中。

如果不满足条件,则从sp中取。

尽可能减少耗时操作调用的次数。

路由的懒加载

对于一个大型app,存在的路由地址数量很大。而ARouter的初始化方法都是在Application中,那么势必导致app加载时间过长。ARouter通过分组懒加载的形式进行加载。

ARouter在初始化的时候,只是加载了分组的类,即路由清单的class,而没有加载详细的路由清单。

public class ARouter$$Root$$app implements IRouteRoot {
  @Override
  public void loadInto(Map<String, Class<? extends IRouteGroup>> routes) {
    routes.put("test", ARouter$$Group$$test.class);
    routes.put("yourservicegroupname", ARouter$$Group$$yourservicegroupname.class);
  }
}

然后当有路由地址跳转的时候,判断是否能查寻对应地址信息,如果没有,则会根据路由地址确定其分组,然后加载该组的路由清单。

 public synchronized static void completion(Postcard postcard) {
        if (null == postcard) {
            throw new NoRouteFoundException(TAG + "No postcard!");
        }
        // 获取路由地址对应的信息
        RouteMeta routeMeta = Warehouse.routes.get(postcard.getPath());
        // 如果为null可能是由于对应组别的路由清单没有加载
        if (null == routeMeta) {    // Maybe its does't exist, or didn't load.
            // 查询对应组的路由清单
            Class<? extends IRouteGroup> groupMeta = Warehouse.groupsIndex.get(postcard.getGroup());  // Load route meta.
            if (null == groupMeta) {
                // 如果不存在,则说明当前路径不存在
                throw new NoRouteFoundException(TAG + "There is no route match the path [" + postcard.getPath() + "], in group [" + postcard.getGroup() + "]");
            } else {
                // Load route and cache it into memory, then delete from metas.
                try {
                    if (ARouter.debuggable()) {
                        logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] starts loading, trigger by [%s]", postcard.getGroup(), postcard.getPath()));
                    }
                    // 加载分组的路由清单
                    IRouteGroup iGroupInstance = groupMeta.getConstructor().newInstance();
                    iGroupInstance.loadInto(Warehouse.routes);
                    // 已加载的路由清单,将其从根节点移除
                    Warehouse.groupsIndex.remove(postcard.getGroup());

                    if (ARouter.debuggable()) {
                        logger.debug(TAG, String.format(Locale.getDefault(), "The group [%s] has already been loaded, trigger by [%s]", postcard.getGroup(), postcard.getPath()));
                    }
                } catch (Exception e) {
                    throw new HandlerException(TAG + "Fatal exception when loading group meta. [" + e.getMessage() + "]");
                }
                // 重新查询
                completion(postcard);   // Reload
            }
        } 
   }

你可能感兴趣的:(android-高级)