github地址:https://github.com/alibaba/ARouter
展示
Demo apk下載猛频、Demo Gif
一辕万、功能介紹
- 支持直接解析標(biāo)準(zhǔn)URL進(jìn)行跳轉(zhuǎn),并自動(dòng)注入?yún)?shù)到目標(biāo)頁(yè)面中
- 支持多模塊工程使用
- 支持添加多個(gè)攔截器儡司,自定義攔截順序
- 支持依賴注入娱挨,可單獨(dú)作為依賴注入框架使用
- 支持InstantRun
- 支持MultiDex(Google方案)
- 映射關(guān)系按組分類、多級(jí)管理捕犬,按需初始化
- 支持用戶指定全局降級(jí)與局部降級(jí)策略
- 頁(yè)面跷坝、攔截器酵镜、服務(wù)等組件均自動(dòng)注冊(cè)到框架
- 支持多種方式配置轉(zhuǎn)場(chǎng)動(dòng)畫
- 支持獲取Fragment
- 完全支持Kotlin以及混編(配置見(jiàn)文末 其他#5)
- 支持第三方 App 加固(使用 arouter-register 實(shí)現(xiàn)自動(dòng)注冊(cè))
- 支持生成路由文檔
- 提供 IDE 插件便捷的關(guān)聯(lián)路徑和目標(biāo)類
二、典型應(yīng)用
- 從外部URL映射到內(nèi)部頁(yè)面柴钻,以及參數(shù)傳遞與解析
- 跨模塊頁(yè)面跳轉(zhuǎn)淮韭,模塊間解耦
- 攔截跳轉(zhuǎn)過(guò)程,處理登陸贴届、埋點(diǎn)等邏輯
- 跨模塊API調(diào)用缸濒,通過(guò)控制反轉(zhuǎn)來(lái)做組件解耦
三、基礎(chǔ)功能
-
添加依賴和配置
android { defaultConfig { ... javaCompileOptions { annotationProcessorOptions { arguments = [AROUTER_MODULE_NAME: project.getName()] } } } } dependencies { // 替換成最新版本, 需要注意的是api // 要與compiler匹配使用粱腻,均使用最新版可以保證兼容 compile 'com.alibaba:arouter-api:x.x.x' annotationProcessor 'com.alibaba:arouter-compiler:x.x.x' ... } // 舊版本gradle插件(< 2.2),可以使用apt插件斩跌,配置方法見(jiàn)文末'其他#4' // Kotlin配置參考文末'其他#5'
-
添加注解
// 在支持路由的頁(yè)面上添加注解(必選) // 這里的路徑需要注意的是至少需要有兩級(jí)绍些,/xx/xx @Route(path = "/test/activity") public class YourActivity extend Activity { ... }
-
初始化SDK
if (isDebug()) { // 這兩行必須寫在init之前,否則這些配置在init過(guò)程中將無(wú)效 ARouter.openLog(); // 打印日志 ARouter.openDebug(); // 開(kāi)啟調(diào)試模式(如果在InstantRun模式下運(yùn)行耀鸦,必須開(kāi)啟調(diào)試模式柬批!線上版本需要關(guān)閉,否則有安全風(fēng)險(xiǎn)) } ARouter.init(mApplication); // 盡可能早,推薦在Application中初始化
-
發(fā)起路由操作
// 1\. 應(yīng)用內(nèi)簡(jiǎn)單的跳轉(zhuǎn)(通過(guò)URL跳轉(zhuǎn)在'進(jìn)階用法'中) ARouter.getInstance().build("/test/activity").navigation(); // 2\. 跳轉(zhuǎn)并攜帶參數(shù) ARouter.getInstance().build("/test/1") .withLong("key1", 666L) .withString("key3", "888") .withObject("key4", new Test("Jack", "Rose")) .navigation();
-
添加混淆規(guī)則(如果使用了Proguard)
-keep public class com.alibaba.android.arouter.routes.**{*;} -keep public class com.alibaba.android.arouter.facade.**{*;} -keep class * implements com.alibaba.android.arouter.facade.template.ISyringe{*;} # 如果使用了 byType 的方式獲取 Service袖订,需添加下面規(guī)則氮帐,保護(hù)接口 -keep interface * implements com.alibaba.android.arouter.facade.template.IProvider # 如果使用了 單類注入,即不定義接口實(shí)現(xiàn) IProvider洛姑,需添加下面規(guī)則上沐,保護(hù)實(shí)現(xiàn) # -keep class * implements com.alibaba.android.arouter.facade.template.IProvider
-
使用 Gradle 插件實(shí)現(xiàn)路由表的自動(dòng)加載 (可選)
apply plugin: 'com.alibaba.arouter' buildscript { repositories { jcenter() } dependencies { classpath "com.alibaba:arouter-register:?" } }
可選使用,通過(guò) ARouter 提供的注冊(cè)插件進(jìn)行路由表的自動(dòng)加載(power by AutoRegister)楞艾, 默認(rèn)通過(guò)掃描 dex 的方式 進(jìn)行加載通過(guò) gradle 插件進(jìn)行自動(dòng)注冊(cè)可以縮短初始化時(shí)間解決應(yīng)用加固導(dǎo)致無(wú)法直接訪問(wèn) dex 文件参咙,初始化失敗的問(wèn)題,需要注意的是硫眯,該插件必須搭配 api 1.3.0 以上版本使用蕴侧!
-
使用 IDE 插件導(dǎo)航到目標(biāo)類 (可選)
在 Android Studio 插件市場(chǎng)中搜索
ARouter Helper
, 或者直接下載文檔上方最新版本
中列出的arouter-idea-plugin
zip 安裝包手動(dòng)安裝,安裝后 插件無(wú)任何設(shè)置两入,可以在跳轉(zhuǎn)代碼的行首找到一個(gè)圖標(biāo) ([圖片上傳失敗...(image-673a43-1584713198828)] ) 點(diǎn)擊該圖標(biāo)净宵,即可跳轉(zhuǎn)到標(biāo)識(shí)了代碼中路徑的目標(biāo)類
四、進(jìn)階用法
-
通過(guò)URL跳轉(zhuǎn)
// 新建一個(gè)Activity用于監(jiān)聽(tīng)Scheme事件,之后直接把url傳遞給ARouter即可 public class SchemeFilterActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Uri uri = getIntent().getData(); ARouter.getInstance().build(uri).navigation(); finish(); } }
AndroidManifest.xml
<activity android:name=".activity.SchemeFilterActivity"> <!-- Scheme --> <intent-filter> <data android:host="m.aliyun.com" android:scheme="arouter"/> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.BROWSABLE"/> </intent-filter> </activity>
-
解析參數(shù)
// 為每一個(gè)參數(shù)聲明一個(gè)字段裹纳,并使用 @Autowired 標(biāo)注 // URL中不能傳遞Parcelable類型數(shù)據(jù)择葡,通過(guò)ARouter api可以傳遞Parcelable對(duì)象 @Route(path = "/test/activity") public class Test1Activity extends Activity { @Autowired public String name; @Autowired int age; // 通過(guò)name來(lái)映射URL中的不同參數(shù) @Autowired(name = "girl") boolean boy; // 支持解析自定義對(duì)象痘括,URL中使用json傳遞 @Autowired TestObj obj; // 使用 withObject 傳遞 List 和 Map 的實(shí)現(xiàn)了 // Serializable 接口的實(shí)現(xiàn)類(ArrayList/HashMap) // 的時(shí)候密任,接收該對(duì)象的地方不能標(biāo)注具體的實(shí)現(xiàn)類類型 // 應(yīng)僅標(biāo)注為 List 或 Map,否則會(huì)影響序列化中類型 // 的判斷, 其他類似情況需要同樣處理 @Autowired List<TestObj> list; @Autowired Map<String, List<TestObj>> map; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ARouter.getInstance().inject(this); // ARouter會(huì)自動(dòng)對(duì)字段進(jìn)行賦值果漾,無(wú)需主動(dòng)獲取 Log.d("param", name + age + boy); } } // 如果需要傳遞自定義對(duì)象她我,新建一個(gè)類(并非自定義對(duì)象類)虹曙,然后實(shí)現(xiàn) SerializationService,并使用@Route注解標(biāo)注(方便用戶自行選擇序列化方式)迫横,例如: @Route(path = "/yourservicegroupname/json") public class JsonServiceImpl implements SerializationService { @Override public void init(Context context) { } @Override public <T> T json2Object(String text, Class<T> clazz) { return JSON.parseObject(text, clazz); } @Override public String object2Json(Object instance) { return JSON.toJSONString(instance); } }
-
聲明攔截器(攔截跳轉(zhuǎn)過(guò)程,面向切面編程)
// 比較經(jīng)典的應(yīng)用就是在跳轉(zhuǎn)過(guò)程中處理登陸事件酝碳,這樣就不需要在目標(biāo)頁(yè)重復(fù)做登陸檢查 // 攔截器會(huì)在跳轉(zhuǎn)之間執(zhí)行矾踱,多個(gè)攔截器會(huì)按優(yōu)先級(jí)順序依次執(zhí)行 @Interceptor(priority = 8, name = "測(cè)試用攔截器") public class TestInterceptor implements IInterceptor { @Override public void process(Postcard postcard, InterceptorCallback callback) { ... callback.onContinue(postcard); // 處理完成,交還控制權(quán) // callback.onInterrupt(new RuntimeException("我覺(jué)得有點(diǎn)異常")); // 覺(jué)得有問(wèn)題疏哗,中斷路由流程 // 以上兩種至少需要調(diào)用其中一種呛讲,否則不會(huì)繼續(xù)路由 } @Override public void init(Context context) { // 攔截器的初始化,會(huì)在sdk初始化的時(shí)候調(diào)用該方法返奉,僅會(huì)調(diào)用一次 } }
-
處理跳轉(zhuǎn)結(jié)果
// 使用兩個(gè)參數(shù)的navigation方法贝搁,可以獲取單次跳轉(zhuǎn)的結(jié)果 ARouter.getInstance().build("/test/1").navigation(this, new NavigationCallback() { @Override public void onFound(Postcard postcard) { ... } @Override public void onLost(Postcard postcard) { ... } });
-
自定義全局降級(jí)策略
// 實(shí)現(xiàn)DegradeService接口,并加上一個(gè)Path內(nèi)容任意的注解即可 @Route(path = "/xxx/xxx") public class DegradeServiceImpl implements DegradeService { @Override public void onLost(Context context, Postcard postcard) { // do something. } @Override public void init(Context context) { } }
-
為目標(biāo)頁(yè)面聲明更多信息
// 我們經(jīng)常需要在目標(biāo)頁(yè)面中配置一些屬性芽偏,比方說(shuō)"是否需要登陸"之類的 // 可以通過(guò) Route 注解中的 extras 屬性進(jìn)行擴(kuò)展雷逆,這個(gè)屬性是一個(gè) int值,換句話說(shuō)污尉,單個(gè)int有4字節(jié)膀哲,也就是32位,可以配置32個(gè)開(kāi)關(guān) // 剩下的可以自行發(fā)揮被碗,通過(guò)字節(jié)操作可以標(biāo)識(shí)32個(gè)開(kāi)關(guān)某宪,通過(guò)開(kāi)關(guān)標(biāo)記目標(biāo)頁(yè)面的一些屬性,在攔截器中可以拿到這個(gè)標(biāo)記進(jìn)行業(yè)務(wù)邏輯判斷 @Route(path = "/test/activity", extras = Consts.XXXX)
-
通過(guò)依賴注入解耦:服務(wù)管理(一) 暴露服務(wù)
// 聲明接口,其他組件通過(guò)接口來(lái)調(diào)用服務(wù) public interface HelloService extends IProvider { String sayHello(String name); } // 實(shí)現(xiàn)接口 @Route(path = "/yourservicegroupname/hello", name = "測(cè)試服務(wù)") public class HelloServiceImpl implements HelloService { @Override public String sayHello(String name) { return "hello, " + name; } @Override public void init(Context context) { } }
-
通過(guò)依賴注入解耦:服務(wù)管理(二) 發(fā)現(xiàn)服務(wù)
public class Test { @Autowired HelloService helloService; @Autowired(name = "/yourservicegroupname/hello") HelloService helloService2; HelloService helloService3; HelloService helloService4; public Test() { ARouter.getInstance().inject(this); } public void testService() { // 1\. (推薦)使用依賴注入的方式發(fā)現(xiàn)服務(wù),通過(guò)注解標(biāo)注字段,即可使用锐朴,無(wú)需主動(dòng)獲取 // Autowired注解中標(biāo)注name之后兴喂,將會(huì)使用byName的方式注入對(duì)應(yīng)的字段,不設(shè)置name屬性焚志,會(huì)默認(rèn)使用byType的方式發(fā)現(xiàn)服務(wù)(當(dāng)同一接口有多個(gè)實(shí)現(xiàn)的時(shí)候瞻想,必須使用byName的方式發(fā)現(xiàn)服務(wù)) helloService.sayHello("Vergil"); helloService2.sayHello("Vergil"); // 2\. 使用依賴查找的方式發(fā)現(xiàn)服務(wù),主動(dòng)去發(fā)現(xiàn)服務(wù)并使用娩嚼,下面兩種方式分別是byName和byType helloService3 = ARouter.getInstance().navigation(HelloService.class); helloService4 = (HelloService) ARouter.getInstance().build("/yourservicegroupname/hello").navigation(); helloService3.sayHello("Vergil"); helloService4.sayHello("Vergil"); } }
-
預(yù)處理服務(wù)
// 實(shí)現(xiàn) PretreatmentService 接口蘑险,并加上一個(gè)Path內(nèi)容任意的注解即可 @Route(path = "/xxx/xxx") public class PretreatmentServiceImpl implements PretreatmentService { @Override public boolean onPretreatment(Context context, Postcard postcard) { // 跳轉(zhuǎn)前預(yù)處理,如果需要自行處理跳轉(zhuǎn)岳悟,該方法返回 false 即可 } @Override public void init(Context context) { } }
五佃迄、更多功能
-
初始化中的其他設(shè)置
ARouter.openLog(); // 開(kāi)啟日志 ARouter.openDebug(); // 使用InstantRun的時(shí)候,需要打開(kāi)該開(kāi)關(guān)贵少,上線之后關(guān)閉呵俏,否則有安全風(fēng)險(xiǎn) ARouter.printStackTrace(); // 打印日志的時(shí)候打印線程堆棧
-
詳細(xì)的API說(shuō)明
// 構(gòu)建標(biāo)準(zhǔn)的路由請(qǐng)求 ARouter.getInstance().build("/home/main").navigation(); // 構(gòu)建標(biāo)準(zhǔn)的路由請(qǐng)求,并指定分組 ARouter.getInstance().build("/home/main", "ap").navigation(); // 構(gòu)建標(biāo)準(zhǔn)的路由請(qǐng)求滔灶,通過(guò)Uri直接解析 Uri uri; ARouter.getInstance().build(uri).navigation(); // 構(gòu)建標(biāo)準(zhǔn)的路由請(qǐng)求普碎,startActivityForResult // navigation的第一個(gè)參數(shù)必須是Activity,第二個(gè)參數(shù)則是RequestCode ARouter.getInstance().build("/home/main", "ap").navigation(this, 5); // 直接傳遞Bundle Bundle params = new Bundle(); ARouter.getInstance() .build("/home/main") .with(params) .navigation(); // 指定Flag ARouter.getInstance() .build("/home/main") .withFlags(); .navigation(); // 獲取Fragment Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation(); // 對(duì)象傳遞 ARouter.getInstance() .withObject("key", new TestObj("Jack", "Rose")) .navigation(); // 覺(jué)得接口不夠多录平,可以直接拿出Bundle賦值 ARouter.getInstance() .build("/home/main") .getExtra(); // 轉(zhuǎn)場(chǎng)動(dòng)畫(常規(guī)方式) ARouter.getInstance() .build("/test/activity2") .withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom) .navigation(this); // 轉(zhuǎn)場(chǎng)動(dòng)畫(API16+) ActivityOptionsCompat compat = ActivityOptionsCompat. makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0); // ps. makeSceneTransitionAnimation 使用共享元素的時(shí)候麻车,需要在navigation方法中傳入當(dāng)前Activity ARouter.getInstance() .build("/test/activity2") .withOptionsCompat(compat) .navigation(); // 使用綠色通道(跳過(guò)所有的攔截器) ARouter.getInstance().build("/home/main").greenChannel().navigation(); // 使用自己的日志工具打印日志 ARouter.setLogger(); // 使用自己提供的線程池 ARouter.setExecutor();
-
獲取原始的URI
String uriStr = getIntent().getStringExtra(ARouter.RAW_URI);
-
重寫跳轉(zhuǎn)URL
// 實(shí)現(xiàn)PathReplaceService接口缀皱,并加上一個(gè)Path內(nèi)容任意的注解即可 @Route(path = "/xxx/xxx") // 必須標(biāo)明注解 public class PathReplaceServiceImpl implements PathReplaceService { /** * For normal path. * * @param path raw path */ String forString(String path) { return path; // 按照一定的規(guī)則處理之后返回處理后的結(jié)果 } /** * For uri type. * * @param uri raw uri */ Uri forUri(Uri uri) { return url; // 按照一定的規(guī)則處理之后返回處理后的結(jié)果 } }
-
生成路由文檔
// 更新 build.gradle, 添加參數(shù) AROUTER_GENERATE_DOC = enable // 生成的文檔路徑 : build/generated/source/apt/(debug or release)/com/alibaba/android/arouter/docs/arouter-map-of-${moduleName}.json android { defaultConfig { ... javaCompileOptions { annotationProcessorOptions { arguments = [AROUTER_MODULE_NAME: project.getName(), AROUTER_GENERATE_DOC: "enable"] } } } }
六、其他
-
路由中的分組概念
- SDK中針對(duì)所有的路徑(/test/1 /test/2)進(jìn)行分組动猬,分組只有在分組中的某一個(gè)路徑第一次被訪問(wèn)的時(shí)候啤斗,該分組才會(huì)被初始化
- 可以通過(guò) @Route 注解主動(dòng)指定分組,否則使用路徑中第一段字符串(/*/)作為分組
- 注意:一旦主動(dòng)指定分組之后赁咙,應(yīng)用內(nèi)路由需要使用 ARouter.getInstance().build(path, group) 進(jìn)行跳轉(zhuǎn)钮莲,手動(dòng)指定分組,否則無(wú)法找到
@Route(path = "/test/1", group = "app")
-
攔截器和服務(wù)的異同
- 攔截器和服務(wù)所需要實(shí)現(xiàn)的接口不同彼水,但是結(jié)構(gòu)類似崔拥,都存在 init(Context context) 方法,但是兩者的調(diào)用時(shí)機(jī)不同
- 攔截器因?yàn)槠涮厥庑苑锔玻瑫?huì)被任何一次路由所觸發(fā)链瓦,攔截器會(huì)在ARouter初始化的時(shí)候異步初始化,如果第一次路由的時(shí)候攔截器還沒(méi)有初始化結(jié)束叛赚,路由會(huì)等待,直到初始化完成稽揭。
- 服務(wù)沒(méi)有該限制俺附,某一服務(wù)可能在App整個(gè)生命周期中都不會(huì)用到,所以服務(wù)只有被調(diào)用的時(shí)候才會(huì)觸發(fā)初始化操作
-
舊版本gradle插件的配置方式
apply plugin: 'com.neenbedankt.android-apt' buildscript { repositories { jcenter() } dependencies { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.4' } } apt { arguments { AROUTER_MODULE_NAME project.getName(); } } dependencies { compile 'com.alibaba:arouter-api:x.x.x' apt 'com.alibaba:arouter-compiler:x.x.x' ... }
-
Kotlin項(xiàng)目中的配置方式
// 可以參考 module-kotlin 模塊中的寫法 apply plugin: 'kotlin-kapt' kapt { arguments { arg("AROUTER_MODULE_NAME", project.getName()) } } dependencies { compile 'com.alibaba:arouter-api:x.x.x' kapt 'com.alibaba:arouter-compiler:x.x.x' ... }
七溪掀、Q&A
-
"W/ARouter::: ARouter::No postcard![ ]"
這個(gè)Log正常的情況下也會(huì)打印出來(lái)事镣,如果您的代碼中沒(méi)有實(shí)現(xiàn)DegradeService和PathReplaceService的話,因?yàn)锳Router本身的一些功能也依賴 自己提供的Service管理功能揪胃,ARouter在跳轉(zhuǎn)的時(shí)候會(huì)嘗試尋找用戶實(shí)現(xiàn)的PathReplaceService璃哟,用于對(duì)路徑進(jìn)行重寫(可選功能),所以如果您沒(méi)有 實(shí)現(xiàn)這個(gè)服務(wù)的話喊递,也會(huì)拋出這個(gè)日志
推薦在app中實(shí)現(xiàn)DegradeService随闪、PathReplaceService
-
"W/ARouter::: ARouter::There is no route match the path [/xxx/xxx], in group [xxx][ ]"
- 通常來(lái)說(shuō)這種情況是沒(méi)有找到目標(biāo)頁(yè)面,目標(biāo)不存在
- 如果這個(gè)頁(yè)面是存在的骚勘,那么您可以按照下面的步驟進(jìn)行排查
- 檢查目標(biāo)頁(yè)面的注解是否配置正確铐伴,正確的注解形式應(yīng)該是 (@Route(path="/test/test"), 如沒(méi)有特殊需求,請(qǐng)勿指定group字段俏讹,廢棄功能)
- 檢查目標(biāo)頁(yè)面所在的模塊的gradle腳本中是否依賴了 arouter-compiler sdk (需要注意的是当宴,要使用apt依賴,而不是compile關(guān)鍵字依賴)
- 檢查編譯打包日志泽疆,是否出現(xiàn)了形如 ARouter::?Compiler >>> xxxxx 的日志户矢,日志中會(huì)打印出發(fā)現(xiàn)的路由目標(biāo)
- 啟動(dòng)App的時(shí)候,開(kāi)啟debug殉疼、log(openDebug/openLog), 查看映射表是否已經(jīng)被掃描出來(lái)梯浪,形如 D/ARouter::: LogisticsCenter has already been loaded, GroupIndex[4]捌年,GroupIndex > 0
-
開(kāi)啟InstantRun之后無(wú)法跳轉(zhuǎn)(高版本Gradle插件下無(wú)法跳轉(zhuǎn))?
因?yàn)殚_(kāi)啟InstantRun之后驱证,很多類文件不會(huì)放在原本的dex中延窜,需要單獨(dú)去加載,ARouter默認(rèn)不會(huì)去加載這些文件抹锄,因?yàn)榘踩蚰嫒穑挥性陂_(kāi)啟了openDebug之后 ARouter才回去加載InstantRun產(chǎn)生的文件,所以在以上的情況下伙单,需要在init之前調(diào)用openDebug
-
TransformException:java.util.zip.ZipException: duplicate entry ....
ARouter有按組加載的機(jī)制获高,關(guān)于分組可以參考 6-1 部分,ARouter允許一個(gè)module中存在多個(gè)分組吻育,但是不允許多個(gè)module中存在相同的分組念秧,會(huì)導(dǎo)致映射文件沖突
-
Kotlin類中的字段無(wú)法注入如何解決?
首先布疼,Kotlin中的字段是可以自動(dòng)注入的摊趾,但是注入代碼為了減少反射,使用的字段賦值的方式來(lái)注入的游两,Kotlin默認(rèn)會(huì)生成set/get方法砾层,并把屬性設(shè)置為private 所以只要保證Kotlin中字段可見(jiàn)性不是private即可,簡(jiǎn)單解決可以在字段上添加 @JvmField
-
通過(guò)URL跳轉(zhuǎn)之后贱案,在intent中拿不到參數(shù)如何解決肛炮?
需要注意的是,如果不使用自動(dòng)注入宝踪,那么可以不寫
ARouter.getInstance().inject(this)
侨糟,但是需要取值的字段仍然需要標(biāo)上@Autowired
注解,因?yàn)?只有標(biāo)上注解之后瘩燥,ARouter才能知道以哪一種數(shù)據(jù)類型提取URL中的參數(shù)并放入Intent中秕重,這樣您才能在intent中獲取到對(duì)應(yīng)的參數(shù) -
新增頁(yè)面之后,無(wú)法跳轉(zhuǎn)厉膀?
ARouter加載Dex中的映射文件會(huì)有一定耗時(shí)悲幅,所以ARouter會(huì)緩存映射文件,直到新版本升級(jí)(版本號(hào)或者versionCode變化)站蝠,而如果是開(kāi)發(fā)版本(ARouter.openDebug())汰具, ARouter 每次啟動(dòng)都會(huì)重新加載映射文件,開(kāi)發(fā)階段一定要打開(kāi) Debug 功能