这两天在使用ARouter时报了一个错误,于是开启ARouter的日志打印(ARouter开启日志看如下代码)看看日志,果然看到有打印“ARouter there’s no route matched”的日志。于是在网上去找解决方案,发现有很多童鞋遇到过这个问题,我也试过这些方法,最终没有解决我遇到的问题。
private void initARouter() {
if (BuildConfig.DEBUG) {
// 两行开启日志代码必须写在init之前,否则这些配置在init过程中将无效
ARouter.openLog(); // 打印日志
ARouter.openDebug();// 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
}
ARouter.init(this);
}
写这篇文章是打算将“ARouter there’s no route matched”的解决方法做一个汇总,建议遇到此问题的童鞋最好看一篇关于ARouter的源码介绍,这有助于了解ARouter,对这个问题的解决有一定的帮助。这里推荐一篇文章,比较简单,点击这里
这是Kotlin项目的正确配置
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
kapt {
arguments {
// ARouter 配置
arg("AROUTER_MODULE_NAME", project.getName())
}
}
android {
// 省略......
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar']
// 省略......
// https://github.com/alibaba/ARouter/blob/master/README_CN.md
api "com.alibaba:arouter-api:$mf_arouter_api"
kapt "com.alibaba:arouter-compiler:$mf_arouter_compiler"
// 省略......
}
当我们的项目是多moudle时,如下图,这是一个多moudle的项目
除了需要像问题1中那样配置外,其他相关模块需要再次配置
kapt “com.alibaba:arouter-compiler:$mf_arouter_compiler”
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
kapt {
arguments {
// ARouter 配置
arg("AROUTER_MODULE_NAME", project.getName())
}
}
android {
// 省略......
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 省略......
// core module kapt需再次依赖 -start
kapt "com.alibaba:arouter-compiler:$mf_arouter_compiler"
// core module kapt需再次依赖 -end
// 省略......
}
具体详情请看移步:
https://blog.csdn.net/qq_25412055/article/details/80651995
这个问题是什么意思呢,我们一般有个主模块,模块名一般叫"app",还有其他一些模块,比如模块“b”,模块“c”,模块“d”等等,其中我们有路由的模块是模块"d",如果我们在“app”模块中只依赖了模块"b"和模块“c”,如下代码所示,那么当我们在app模块或者模块“b”中通过ARouter跳转到模块“d”时就无法跳转,同时在build项目时也会打印“ARouter there’s no route matched”
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(":b")
implementation project(":c")
// 省略......
}
那么正确的做法是也要引入模块“d”,如下图代码所示
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(":b")
implementation project(":c")
// 也要依赖路由模块d
implementation project(":d")
// 省略......
}
问题分析,建议看到这里的童鞋最好先了解一下ARouter的源码,请看这篇
我简单贴一下ARouter中的源码,它有个工具类ClassUtils
/**
* 通过指定包名,扫描包下面包含的所有的ClassName
*
* @param context U know
* @param packageName 包名
* @return 所有class的集合
*/
public static Set<String> getFileNameByPackageName(Context context, final String packageName) throws PackageManager.NameNotFoundException, IOException, InterruptedException {
final Set<String> classNames = new HashSet<>();
List<String> paths = getSourcePaths(context);
final CountDownLatch parserCtl = new CountDownLatch(paths.size());
for (final String path : paths) {
DefaultPoolExecutor.getInstance().execute(new Runnable() {
@Override
public void run() {
DexFile dexfile = null;
try {
if (path.endsWith(EXTRACTED_SUFFIX)) {
//NOT use new DexFile(path), because it will throw "permission error in /data/dalvik-cache"
dexfile = DexFile.loadDex(path, path + ".tmp", 0);
} else {
dexfile = new DexFile(path);
}
Enumeration<String> dexEntries = dexfile.entries();
while (dexEntries.hasMoreElements()) {
String className = dexEntries.nextElement();
if (className.startsWith(packageName)) {
classNames.add(className);
}
}
} catch (Throwable ignore) {
Log.e("ARouter", "Scan map file in dex files made error.", ignore);
} finally {
if (null != dexfile) {
try {
dexfile.close();
} catch (Throwable ignore) {
}
}
parserCtl.countDown();
}
}
});
}
parserCtl.await();
Log.d(Consts.TAG, "Filter " + classNames.size() + " classes by packageName <" + packageName + ">");
return classNames;
}
我们重点看下代码
Enumeration<String> dexEntries = dexfile.entries();
while (dexEntries.hasMoreElements()) {
String className = dexEntries.nextElement();
if (className.startsWith(packageName)) {
classNames.add(className);
}
}
dexEntries有着App中所有已加载模块的类,如果我们不依赖模块“d”,那么dexEntries是没有模块"d"中的所有类的,ARouter的路由map也就不会缓存我们的路由类了,也就找不到路由类,打印“ARouter there’s no route matched”,
@Route(path = ProductRouter.sProductQuickInstallDescription, name = "提供支持QuickInstall协议的设备的统一服务")
object ProductQuickInstallDescription : IProductQuickInstallDescription {
private var context: Context? = null
// 其他代码省略
这是Kotlin的单例类,也找不到,正确写法如下。(写的比较仓促,未深究原因)
@Route(path = ProductRouter.sProductQuickInstallDescription, name = "提供支持QuickInstall协议的设备的统一服务")
class ProductQuickInstallDescription : IProductQuickInstallDescription {
private var context: Context? = null
// 其他代码省略