ARouter 攔截器之多 module 獨立執行

code小生發表於2021-10-28
本文已首發微信公眾號「code小生」,大家可以搜尋關注,專注安卓技術分享。

本文說明

上篇文章已分享了路由配置、跳轉、原理、完整的效果演示gif以及原始碼,而且是多 module 專案演示的,算是路由 ARouter 的入門,還沒配置使用的可以先去看看。

本文的內容主要涉及如下兩個:

  • 路由攔截器使用
  • module 獨立執行

前者在我們開發中有這樣一種應用場景,預設使用者不登入可以瀏覽一部分頁面,當點選部分頁面的時候就需要先去登入,也就是跳轉到登入頁面,普通的做法是根據需求挨個去做點選事件,這就很麻煩,如果需要跳轉登入的時候傳遞引數啥的,那就改動超級大了;而路由ARouter的攔截器功能就很好的解決了這個問題,還支援自定義攔截器,使用起來很靈活。

後者的使用場景適合專案大,多人開發的情景,這樣可以各自負責一個模組,獨立除錯執行,利於專案管理以及程式碼的維護。這塊在上一篇文章的前提下還需要額外配置,本文會講。

module 獨立執行

先來看看module獨立執行,然後我們在各個模組做一個模擬的跳轉頁面需要驗證登入的示例,這樣比較清晰。

第一步:配置 gradle.properties

gradle.properties 檔案中新增如下程式碼

#是否需要單獨執行某個模組 true:表示某個模組不作為依賴庫使用
isSingleCircleModule=true
#isSingleCircleModule=false
isSingleHomeModule=true
#isSingleHomeModule=false

第二步:配置app下的build.gradle

在app下的build.gradle檔案配置

if (!isSingleCircleModule.toBoolean()) {
    implementation project(path: ':circle')
}
if (!isSingleHomeModule.toBoolean()){
    implementation project(path: ':home')
}

並註釋掉原來的依賴

//    implementation project(path: ':circle')
//    implementation project(path: ':home')

第三步:配置各獨立模組下的build.gradle

circle模組下build.gradle檔案最頂部改動如下:

//plugins {
//    id 'com.android.library'
//}

if (isSingleCircleModule.toBoolean()) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

home模組下build.gradle檔案最頂部改動如下:

//plugins {
//    id 'com.android.library'
//}

if (isSingleHomeModule.toBoolean()) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

第四步:看效果

上面的配置完成後,點選Sync Project with Gradle Files 等待編譯完成,可看到如下狀態:

Select Run彈窗

這個時候我們選擇其中一個module執行,會發現報錯如下:

Could not identify launch activity: Default Activity not found
Error while Launching activity

很明顯,我們都知道Android程式的主入口是從清單檔案配置的,但我們的各module都還沒有做這個工作。

circle模組下的清單檔案中,配置如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.gs.circle">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/app_icon"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".CircleActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
其中的iconlabel以及theme都可以定義在baselib中,這樣我們任何 module 配置的時候就可以直接引用,而無需各自複製一份了;除此之外,values資料夾下的東西都可以移動到baselib下,方便其他模組引用,這也就是baselib模組的作用,如果你要細分,還可以j將公共資源放在一個獨立的模組裡,這個模組通常叫做:commonlib,具體情況而定。

配置完清單檔案,執行後發現桌面會多出來一個 APP icon,開啟只有一個頁面,就是我們的circlemodule的主頁面。home模組的清單配置就不展示了,下面看下效果:

module獨立執行

這個時候再切回去執行app模組,如果發現有問題,先解除安裝再執行就ok了。但是會有一個問題,原來可以跳轉其他模組的功能,現在跳轉不了了,這其實很正常,因為在元件化開發模式下,每個 module 都是獨立的app,所以肯定不能直接跳轉過去。

那如何實現正常跳轉呢?

需要兩步,將gradle.properties中的程式碼修改為如下:

#isSingleCircleModule=true
isSingleCircleModule=false
#isSingleHomeModule=true
isSingleHomeModule=false

接著將circlehome模組的清單檔案中的 application屬性和預設啟動配置項刪掉,然後再執行就 ok 了。

如果想將其中一個作為依賴庫使用,那麼就指匠情挑設定為false即可。

關於元件之間 AndroidManifest 合併問題

其實這個可以在正式打包的時候,註釋掉module中的相關程式碼即可,畢竟是在元件模式。那有沒有辦法解決每次都要註釋的問題呢?答案是yes.

大致思路如下:

在可獨立執行的module的res->main資料夾下新建一個資料夾(命名自定義),然後將對應的清單檔案複製一份,名稱不需要修改,內容的差別就是前面提到的,去掉application屬性和預設啟動配置項。<br/>
接著在對應 module 的 build.gradle 中指定表單的路徑,程式碼如下:
sourceSets {
    main {
        if (isSingleCircleModule.toBoolean()) {
            manifest.srcFile 'src/main/module/AndroidManifest.xml'
        } else {
            manifest.srcFile 'src/main/AndroidManifest.xml'
        }
    }
}

這樣在不同的開發模式下就會讀取到不同的 AndroidManifest.xml ,然後我們需要修改這兩個表單的內容以為我們不同的開發模式服務。

單模組獨立執行小結

優點:

  • 專案耦合度低,開發效率高,出現問題易排查
  • 利於專案進度管理,分工明確
  • 適合多人大專案

缺點:

  • 前期配置比較複雜,開發過程中需要修改部分配置
  • 穩定性不好把握,畢竟不是google官方出的框架,後期出問題不好處理

其實還有很多問題,實踐過的應該明白,每個專案都有自己的獨特之處,會有各種各樣的奇怪問題,但一般網上我們都可以找到解決方案。

路由攔截器使用

首先還是需要新增幾個配置,在工程下的build.gradle檔案中新增下面這行程式碼:

classpath 'com.alibaba:arouter-register:1.0.2'

app模組的build.gradle檔案下,配置改動如下:

plugins {
    id 'com.android.application'
    id 'com.alibaba.arouter' // 攔截器必須配置
}

配置完這兩步,按照慣例,該是編譯了。

為了演示,我這裡在app下新建一個名為LoginActivity的頁面,作業登入攔截後跳轉的頁面,頁面內容只有一個提示文字,這裡補貼程式碼。

然後分別在宿主模組app、功能模組circlehome中去做跳轉登入頁面,看看我們的攔截器是否起到了攔截作用,下面開始定義攔截器。

要獨立執行某個模組,這裡就不再贅述了,大家自行修改配置即可。

攔截器完整程式碼如下:

/**
 * Description: 登入攔截器
 * Date: 2021/10/9 10:42
 * <p>
 * 攔截器會在跳轉之間執行,多個攔截器會按優先順序順序依次執行
 * * <p>
 * * priority 數值越小許可權越高
 */
@Interceptor(priority = 2, name = "登入ARouter攔截器")
public class LoginInterceptor implements IInterceptor {

    private Context mContext;

    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {
        boolean isLogin = mContext.getSharedPreferences("arouterdata", mContext.MODE_PRIVATE).getBoolean("isLogin", false);
        if (isLogin) {
            callback.onContinue(postcard);
        } else {
            switch (postcard.getPath()) {
                // 需要登入的攔截下來
                case ARouterPath.APP_MY_INFO:
                    ARouter.getInstance().build(ARouterPath.LOGIN_PAGE).with(postcard.getExtras()).navigation();
                    break;
                default:
                    callback.onContinue(postcard);
                    break;
            }
        }
    }

    /**
     * 攔截器的初始化,會在sdk初始化的時候呼叫該方法,僅會呼叫一次
     *
     * @param context
     */
    @Override
    public void init(Context context) {
        mContext = context;
    }

}

攔截器初始化需要重新安裝才會生效,這點要注意。攔截器是不需要我們手動顯示呼叫的,而是框架通過註解來使用的,所以我們只需要寫好邏輯程式碼即可。

以上程式碼可以實現模組內和跨模組跳轉攔截,本地的登入狀態我這裡沒有處理邏輯,所以每次都會被攔截到。下面看效果:

攔截器效果

演示效果模擬進入MyInfoActivity頁面時需要先登入,分別從三個模組做了跳轉演示。

總結

元件化module獨立執行與合併操作起來相對繁瑣一點,但優點也很明顯。路由框架ARouter的攔截器使用起來就很簡單了,其實攔截器完全可以在學完上一篇之後,直接使用,如果元件化多模組獨立執行實際專案使用不到,可以先跳過,簡單瞭解流程即可。

Android的框架演變也很快,“三化技術”在兩年前特別火,幾乎大家都在討論,但並沒有持續多長時間就被新出的技術替代了,而作為一個開發者,自己需要掌握一個基本技能:從零開始搭建一個專案框架,並且這個框架儘可能的要跟上專案的持續發展

本文全部程式碼已打包:關注微信公眾號code小生回覆arouter

相關文章