Android开发问题记录-ARouter init logistics center exception
16lz
2021-01-23
在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 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() + "]"); } }
从代码可知,如果处于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
中多了
这个模块。
确定了问题所在,解决就简单了:在研发和测试阶段,把ARouter.openDebug()打开,而在正式发布的版本,则不打开。
更多相关文章
- Android静态代码分析
- 【Android】附加Android源代码Androidandroid_gingerbread_javas
- Android中对NFC的实现代码分布在如下几个地方:
- Android简明开发教程二十四篇及示例代码下载
- Android ROM研究---如何在ubuntu下下载姜饼(Gingerbread)源代码
- Android最佳实践(六)之扫描二维码模块
- Android手机重启的核心代码
- Android加载对话框,异步执行代码的封装类
- Android 的一些比较好的开源代码项目