Android开发问题记录-ARouter init logistics center exception

在Bugly中发现存在偶现的崩溃问题如下:

	#5404 com.alibaba.android.arouter.exception.HandlerException

更详细的信息如下:

java.lang.RuntimeException:Unable to create application com.xxx: 
com.alibaba.android.arouter.exception.HandlerException: ARouter::ARouter init logistics center exception! 
[com.alibaba.android.arouter.routes.ARouter$$Providers$$yyy]

看了ARouter所有与之相关的Issues,并没有发现解决方案。

于是查看ARouter源码,定位到如下代码,LogisticsCenter::init

    /**
     * LogisticsCenter init, load all metas in memory. Demand initialization
     */
    public synchronized static void init(Context context, ThreadPoolExecutor tpe) throws HandlerException {
        mContext = context;
        executor = tpe;

        try {
            long startInit = System.currentTimeMillis();
            //billy.qi modified at 2017-12-06
            //load by plugin first
            loadRouterMap();
            if (registerByPlugin) {
                logger.info(TAG, "Load router map by arouter-auto-register plugin.");
            } else {
                Set<String> 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<String>()));
                }

                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() + "]");
        }
    }

从代码可知,如果处于debuggable()或者apk的版本号变更时,ARouter会重新通过指定包名,扫描包下面包含的所有的ClassName。否则,ARouter会从缓存SharedPreferences中读取这些信息。

由于问题堆栈[com.alibaba.android.arouter.routes.ARouter$$Providers$$yyy],这里的yyy模块,我们在最近移除过,因此,考虑是因为缓存中有yyy模块,但是实际新的apk中并没有。

我们到/data/data/包名/shared_prefs/SP_AROUTER_CACHE.xml下查看,果然ROUTER_MAP中多了<string>com.alibaba.android.arouter.routes.ARouter$$Group$$yyy</string>这个模块。

确定了问题所在,解决就简单了:在研发和测试阶段,把ARouter.openDebug()打开,而在正式发布的版本,则不打开。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]:综上可见,如果clone了一个含有子项目和第三方库的项目代码时,需要执行git submodule update --remote和git submodule update --init两个命令,或者调整先后,才能正确编译。\[1\]引用\[2\]:打开终端,输入以下命令:mkdir -p ~/esp cd ~/esp git clone --recursive https://github.com/espressif/esp-idf.git。\[2\]引用\[3\]:这里我猜测clone命令不再有效的原因是:.git中记录该子模块的版本信息,所以当git命令,扫描到该子模块时,已经有文件夹和版本信息,所以不再clone,认为已经存在。\[3\] 问题:git submodule update --init --是什么意思? 回答: git submodule update --init --命令用于初始化并更新子模块。其中,--init选项用于初始化子模块,--update选项用于更新子模块。通过执行这个命令,可以确保子模块的文件夹和版本信息都正确地被克隆和更新。 #### 引用[.reference_title] - *1* [git submodule update --init 和 --remote的区别](https://blog.csdn.net/fanyun_01/article/details/114237342)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [git submodule update --init --recursive失败的处理办法](https://blog.csdn.net/qq_20016593/article/details/127500880)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值