路由框架ARouter使用及源碼解析(一) 系列文章:

系列文章:

路由框架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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章