系列文章:
路由框架ARouter使用及源碼解析(一)
路由框架ARouter使用及源碼解析(二)
一、什麼是路由?
路由是指路由器從一個接口上收到數據包,根據數據路由包的目的地址進行定向並轉發到另一個接口的過程。—百度百科
以Android爲例,各個組件module可以看成一個個網絡,而路由就可以看成是各個模塊頁面跳轉的中轉站,除了中轉以外,路由還可以過濾或攔截一些不安全或不規範的跳轉。
二、阿里ARouter
官方定義:A framework for assisting in the renovation of Android componentization (幫助 Android App 進行組件化改造的路由框架)
其實Android的跳轉已經提供了Intent,Intent不僅可以顯示跳轉,也可以隱式跳轉。那麼ARouter爲什麼還會存在呢?讓我們對比一下原生跳轉和路由跳轉:
1、原生顯示跳轉必須依賴於類,強耦合,而隱式跳轉需要都在AndroidManifest裏集中註冊,協作麻煩;而路由跳轉通過URL索引,低耦合,協作方便;
2、原生在通過staryActivity啓動跳轉後就交由系統控制,並不能做攔截;路由跳轉可以對跳轉做過濾或攔截。
通過對比,我們發現路由特別適合用來做跳轉(尤其是組件間的通信及跳轉),下面就來看一下阿里ARouter的集成及使用吧~
2.1、配置&初始化
在app的build.config中配置:
compile 'com.alibaba:arouter-api:1.4.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'
在各個需要使用ARouter模塊的build.gradle的defaultConfig配置中加入:
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
注意:新版本已經改成AROUTER_MODULE_NAME來獲取module名字了。
上面配置中,annotationProcessor用來聲明註解解析器,arouter-compiler用來解析ARouter中的各個註解(後面會講到),通過APT方式在編譯期間自動生成class類,關於annotationProcessor可以查看下面這篇文章:
https://blog.csdn.net/xx326664162/article/details/68490059
配置完成後,進行初始化:
在自定義Application中進行初始化:
if (BuildConfig.DEBUG) {
// 打印日誌
ARouter.openLog();
// 開啓調試模式(如果在InstantRun模式下運行,必須開啓調試模式!線上版本需要關閉,否則有安全風險)
ARouter.openDebug();
}
// 儘可能早,推薦在Application中初始化
ARouter.init(this);
初始化完成後,就可以開始使用了~
2.1、基本跳轉
以Activity跳轉爲例,比如從Activity1跳轉到Activity2,首先在1、目標Activity2中:
@Route(path = MConstant.ACTIVITY2)
public class Activity2 extends Activity {
}
Activity2添加註解@Route,path是跳轉路徑,一般都寫在統一的一個類中,方便維護:
public class MConstant {
public static final String ACTIVITY2 = "/main/activity2";
public static final String TRANSFER_KEY = "transfer_key";
}
2、在Activity1中進行ARouter注入並實現跳轉:
public class Activity1 extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ARouter.getInstance().inject(this);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ARouter.getInstance().build(MConstant.ACTIVITY2).navigation();
}
});
}
上面就實現了簡單的頁面跳轉,如果想傳遞參數,可以用下面的方式:
ARouter.getInstance().build(path).withString(MConstant.TRANSFER_KEY,"value").navigation();
withXXX處填的是參數的key和value (如果ARouter傳遞的是對象,首先該對象需要Parcelable或者Serializable序列化) ,navigation發射了路由跳轉。在目標類中,通過註解@Autowired來獲取傳遞值:
public class Activity2 extends Activity {
@Autowired(name = TRANSFER_KEY)
public String qrText;
}
2.3、獲取Fragment實例
首先在Fragment上使用註解@Route
@Route(path = "/test/fragment")
public class BlankFragment extends Fragment {
}
獲取Fragment實例:
Fragment fragment = (Fragment) ARouter.getInstance().build("/test/fragment").navigation();
通過上面的代碼就可以獲取Fragment的實例,這在跨模塊中使用Fragment是很有用的。
2.4、進階用法之攔截器&通過URL跳轉
攔截器:
@Interceptor(priority = 1)
public class MyInterceptor implements IInterceptor {
private Context context;
@Override
public void process(Postcard postcard, InterceptorCallback callback) {
if (MConstant.ACTIVITY2.equals(postcard.getPath())) {
//如果是跳轉Activity2,則攔截
callback.onInterrupt(null);
} else {
callback.onContinue(postcard);
}
}
@Override
public void init(Context context) {
this.context = context;
}
}
攔截器需要實現IInterceptor並通過註解@Interceptor來聲明,其中多個攔截器的優先級根據priority來判斷,值越小優先級越高。
通過URL跳轉:
Uri testUriMix = Uri.parse("arouter://m.aliyun.com/main/activity2");
ARouter.getInstance().build(testUriMix)
.withString("key1", "value1")
.navigation();
跟上面介紹的普通跳轉幾乎一樣,上面是用的path跳轉,而這裏使用的是URL跳轉,一般在自定義協議(如webview)時,使用URL跳轉非常的方便,並且可以對URL做攔截、轉換等。
2.5、服務管理
比如ModuleA中想調用ModuleB中的方法,在公共引用庫中聲明接口並繼承IProvider:
public interface IModuleService extends IProvider {
String getModuleName();
}
在ModuleB中定義接口實現類:
@Route(path = MConstant.MODULE_SERVICE)
public class ChatModuleService implements IModuleService {
@Override
public String getModuleName() {
return "chatModule";
}
@Override
public void init(Context context) {
}
}
在ModuleA中調用:
//1、通過類名調用服務
IModuleService service = ARouter.getInstance().navigation(IModuleService.class);
String getName = service.getModuleName();
Log.e("TTT", "getName is " + getName);
//2、通過路徑名稱調用服務
IModuleService service1 = (IModuleService) ARouter.getInstance().build(MConstant.MODULE_SERVICE).navigation();
String getName1 = service1.getModuleName();
Log.e("TTT", "getName1 is " + getName1);
上面兩種方式都可以最終得到ModuleB中的數據。
2.6、降級方案
ARouter.getInstance().build("/xxx/xxx").navigation(this, new NavCallback() {
@Override
public void onFound(Postcard postcard) {
Log.d("ARouter", "找到了");
}
@Override
public void onLost(Postcard postcard) {
Log.d("ARouter", "找不到了");
}
@Override
public void onArrival(Postcard postcard) {
Log.d("ARouter", "跳轉完了");
}
@Override
public void onInterrupt(Postcard postcard) {
Log.d("ARouter", "被攔截了");
}
});
當跳轉失敗時,可以通過回調得到結果並做相應處理。
三、引用
【1】ARouter: https://github.com/alibaba/ARouter
【2】APT、annotationProcessor、android-apt、Provided、自定義註解:
https://blog.csdn.net/xx326664162/article/details/68490059