Android模塊化、組件化開發封裝(mvp、retrofit2、rxjava2)組合框架

題外話:這一兩年來隨着人工智能的火爆,越來越多的人都去做AI、人工智能什麼的,移動互聯網的風口位置也已讓賢,但是不在風口,我們也得堅持安卓下去,不是什麼火我們就往那裏拱(拱 二聲,四川話:去),新技術總有一天也會失去衆人的焦點被其他新事物所取代,所以堅持下去,我們會做的更好的。

前言:在我們日常開發中,當項目業務逐漸變得多起來,在app目錄下懟代碼感覺會越來越臃腫,有時還會耦合的很嚴重,最要命最痛苦的是編譯的時候,一個小改動改個字符串什麼的可能幾秒鐘就完成了,但等待編譯卻要好幾分鐘,更甚至十幾分鍾,這肯定是不能忍的,畢竟我們工作時間很寶貴,能不拖時間就不拖,免得影響下班時間,對吧。所以這個時候,安卓模塊化就顯得格外重要了。

注意:這裏只着重講怎麼去架構,還有常用的思路方法,深層次的原理等不大會涉及到,如果大家有需要看原理什麼的就去看其他大牛的講解哦!

一、模塊化解決的問題:

1.各個module間互不依賴,形成解耦。

2.各個模塊作爲application時可以單獨運行,作爲library時,只提供給app模塊依賴打包使用。

3.便於各個開發人員間的合作開發。

4.編譯時間減少,程序員心情值up。

下面將根據demo來講解具體用法:

二、首先看到android目錄架構

包括上方紅框的基礎組件lib_common以及lib_opensource,lib_opensource作用是所有三方庫的一個依賴組件,lib_opensource只被lib_common依賴。lib_common作用是提供所有base類,包括封裝的mvp、封裝過的網絡框架、基本配置類、utils。當然如果說業務具有登錄註冊的,那麼也可以直接放到裏面,當我們單獨編譯某一個模塊又必須要用到登錄時,那麼此時所有業務子模塊就直接依賴lib_common就足夠了,當我們需要整體編譯打包時,app模塊只需要依賴各個業務子模塊,不需要依賴lib_common。

1.怎麼去配置是否單獨編譯還是整體打包編譯:

我們需要去定義一個全局的變量,讓我們各個子模塊自動去識別這個變量就行。具體做法:

在項目根目錄的 gradle.properties 中定義變量:

在所有需要單獨編譯的子模塊的build.gradle 中加入紅框代碼:

上面的isBuildModule 爲true表示,子模塊會以application存在,即可單獨打包編譯等,當爲false時,作爲library供application依賴使用。

此時還需要注意兩點:

1)當子模塊作爲library時,子模塊的build.gradle中不需要 applicationId這個字段,而當作爲application時則需要這個字段。我們同樣根據isBuildModule字段來判斷:

2)子模塊作爲library時,是由app主模塊啓動的,而子模塊作爲application時是自己本身啓動,所以此時需要配置兩個不同清單文件release版和debug版,debug是需要配置啓動頁面的,如下:

             

debug 模式下的 AndroidManifest.xml :

<application
   ...
   >
   <activity
       android:name="com.senon.module_art.ArtMainActivity"
       android:label="module_art">
       <intent-filter>
           <action android:name="android.intent.action.MAIN" />
           <category android:name="android.intent.category.LAUNCHER" />
       </intent-filter>
   </activity>
</application>

realease 模式下的 AndroidManifest.xml :

<application
   ...
   >
   <activity
       android:name="com.senon.module_art.ArtMainActivity"
       android:label="module_art">
       <intent-filter>
           <category android:name="android.intent.category.DEFAULT" />
           <category android:name="android.intent.category.BROWSABLE" />
           <action android:name="android.intent.action.VIEW" />
           <data android:host="com.senon.module_art"
               android:scheme="router" />
       </intent-filter>
   </activity>
</application>

當寫好了兩個不同版本的清單文件之後,我們需要在對應的子模塊的build.gradle去配置不同版本的清單文件

2.三方依賴庫如何使用:

上面提到的lib_opensource模塊是專門存放三方開源等依賴,使用方法一般是在根目錄新建一個gradle腳本文件,我們命名爲dependencies.gradle,我們把所有的三方依賴全部放在裏面,並定義新的名稱方便調用,如下:

然後在項目工程根build.gradle中去使用這個dependencies.gradle

接下來,lib_common的build.gradle中依賴lib_opensource這個模塊,如下:

注意到上面紅框裏面了嗎? 依賴用的是api 而不是implementation。爲什麼尼?

原因是安卓3.0以後google爲了安卓的規範,而使用了api和implementation來替代以前的compile,api和以前的compile作用是一樣的,而implementation的出現是爲了依賴私有化(我個人這樣理解的)。如果B implementation了A,那麼B可以調用到A中的api接口(也就是A中的各種類,接口之類的),此時如果C implementation了B,那麼C是不能夠調用到A中的api接口的,所以說implementation是保護了A中的api接口的,這樣做增加了項目的構建速度,非常棒。

回過來,如果我們想要C也可以調用A的接口,怎麼辦尼?這時就應該用api了,B api A,C implementation B,此時C就能夠調用A的api接口了。現在發散下思維(偷笑),如果D implementation C,D想調用A中的api接口怎麼辦?

 

三、程序是否運行在debug模式

在程序中,我們常常會用到一個全局標誌位,來進行一下debug配置,比如最常見的就是在Application中配置log日誌開關,debug時開啓方便調試觀察,release時關閉log,否則可能出現安全問題。這個標誌位很重要,有些框架必須配置debug模式,比如接下來我們會用到的三方路由框架ARouter,如果在debug模式下運行,則必須開啓調試模式!而線上版本需要關閉ARouter,否則也有安全風險。

四、模塊間的跳轉問題

由於子模塊之間是禁止互相依賴的,所以他們之間不能跳轉、傳值等,一般來說解決這個問題有幾種方法,一是隱式跳轉,但不方便傳值及後期維護修改,二是最常用的路由跳轉,我們項目中所用的路由跳轉爲阿里巴巴開源ARouter,使用起來比較簡單:

1,添加依賴和配置
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'
    ...
}

2,初始化路由,一般在Application中。

if (isDebug()) {           // 這兩行必須寫在init之前,否則這些配置在init過程中將無效
    ARouter.openLog();     // 打印日誌
    ARouter.openDebug();   // 開啓調試模式(如果在InstantRun模式下運行,必須開啓調試模式!線上版本需要關閉,否則有安全風險)
}
ARouter.init(mApplication); // 儘可能早,推薦在Application中初始化

3,定義爲被跳轉的目標頁面註冊路由:

一般的路由地址由兩級或多級構成,我們可以統一規定路徑地址爲 /模塊名/包名/類名,也可以直接定義爲  /模塊名/類名,只要類名不重複就ok,具體如何使用請查看ARouter官方文檔。

我這裏要講的是如何封裝路由地址,封裝過後對以後的迭代有幫助。我們在lib_common建一個常量類,所以路由跳轉均寫入本ConstantArouter方便調用, 我們規定路由跳轉命名統一用:path+模塊名+Activity名

我們在目標頁面註冊路由就可以改爲 @Route(path = ConstantArouter.PATH_APP_FRAGMENTHOMEACTIVITY)

4.接下來我們討論下這個需求,每個子模塊都可以被單獨編譯打包,但是每個模塊也都需要登錄操作,並拿到登錄時的數據以進行下面的流程,這時候怎麼辦尼?難道每個子模塊都寫一個登錄註冊業務,然後將數據保存在各個模塊! 對,理論上這種方法可行,但如果這時登錄業務變了,比如頁面操作變了,接口數據結構返回變了,難道我們還要一個一個模塊去修改嗎?這樣肯定就不行了嘛!我們的時間很寶貴,我們只想要修改一個地方的登錄就能應用到全部的子模塊包括app模塊,接下來我將根據ARouter來封裝一個簡單易懂操作方便的類來節省我們的開發時長。

5.未完待續!

 

 

 

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