android 組件化

隨着移動端快產品速迭代,多人合做已成爲一種標杆,若是是傳統的項目都放在一個module中代碼耦合嚴重,存在各類各樣的詬病,因此組件化愈來愈盛行。下面咱們一步步揭開組件化的神祕面紗。android

首先咱們看下總體結構

說明:app是殼工程,下面是業務模塊分別有login,my等模塊,業務模塊都依賴libmvi基礎庫,

基礎庫裏面有業務組件都會用到的功能好比:基礎類、glide、retrofit等,有些組價用到,有些用不到的工具模塊,單獨抽成工具模塊好比libutil,libshare,可被組件按需依賴。git

實施組件化

模塊劃分

按項目業務抽取module和工具模塊,爲了方便管理,抽取config.gradle作版本統一管理,util.gradle作工具模塊依賴......github

單獨編譯

在gradle.properties中聲明isBuildModule,isBuildModule 爲 true 時可使每一個組件獨立運行, false 則能夠將全部組件集成到宿主 App 中,編寫業務module.gradle,每一個業務組件必須依賴這個。bash

單獨編譯須要新建alone文件夾放入AndroidManifest.xml標識啓動入口,關於源碼控制和isBuildModule 切換詳見module.gradle配置markdown

if (isBuildModule.toBoolean()) {
    apply plugin: 'com.android.application'
    configSigning project
} else {
    apply plugin: 'com.android.library'
}
 sourceSets {
        main {
            if (isBuildModule.toBoolean()) {
                //獨立運行
                manifest.srcFile 'src/main/alone/AndroidManifest.xml'
            } else {
                //合併到宿主
                manifest.srcFile 'src/main/AndroidManifest.xml'
                resources {
                    //正式版本時,排除alone文件夾下全部調試文件
                    exclude 'src/main/alone/*'
                }
            }
        }
    }
複製代碼

Application業務分發

之前的項目第三方的初始化全在 項目的application中作的,如今組件化須要單一職責,不一樣的三方庫的初始化放到不一樣的業務模塊,具體步驟以下:app

1.新建module模塊:providerservice (做爲組件通訊和application業務分發),業務模塊需依賴它進行通訊mvvm

2.新建interface IApp ,代理生命App週期maven

interface IApp {

    fun attachBaseContext(base: Context)

    fun onCreate(base: Context)

    fun onTerminate(base: Context)
}
複製代碼

3.不一樣的業務模塊實現IApp,並在對應AndroidManifest.xml註冊ide

class LoginApp: IApp {
    override fun attachBaseContext(base: Context) {
    }

    override fun onCreate(base: Context) {
	//初始化一鍵登陸,第三方庫啥的
    }

    override fun onTerminate(base: Context) {
    //釋放一些資源
    }
}

<meta-data
                android:name="com.ikang.loginmodule.LoginApp"
                android:value="ConfigAppLife" />
複製代碼

4.編寫CommonManifestParser解析全部的ConfigAppLife到集合中,再編寫代理類AppDelegate,代理全部模塊的生命週期函數調用,最後在BaseApp相應調用。函數

// CommonManifestParser
  val appInfo =context.packageManager.getApplicationInfo( context.packageName, PackageManager.GET_META_DATA)
            if (appInfo.metaData != null) {
                for (key in appInfo.metaData.keySet()) {
                    if (MODULE_VALUE == appInfo.metaData[key]) {
                        modules.add(parseModule(key))
                    }
                }
            }
           
   //  BaseApp      
 override fun onTerminate() {
        super.onTerminate()
        mAppDelegate.onTerminate(this)
 }
複製代碼

業務組件通訊

①採用原始方式

一、providerservice模塊中在聲明接口IService,而後在聲明登錄模塊暴露的功能有哪些

interface ILoginService : IService {
   val accountId: String
}
複製代碼

二、在登錄模塊loginmodule實現ILoginService

class LoginServiceImpl : ILoginService {
    override val accountId: String = "張三"
}
複製代碼

三、在loginApp傳入實現

class LoginApp: IApp {

    override fun onCreate(base: Context) {
        //傳統方式通訊
	     LoginServiceControl.accountService = LoginServiceImpl()
    }
       ......
複製代碼

4.如今便可在mymodule模塊MeFragment中獲取登錄模塊的用戶Id

LoginServiceControl.accountService.accountId
複製代碼

②採用arouter通訊跟上面的相似,只不過arouter是編譯期apt自動生成代碼,放入到路由表map中的,而後掃描全部的dex中的指定報名的IProvider實現的

一、providerservice模塊中在聲明接口ILoginService ,而後在聲明登錄模塊暴露的功能有哪些

interface ILoginService :IProvider {
    val accountId: String
}
複製代碼
  • 2.在登錄模塊loginmodule實現ILoginService
@Route(path = ProviderPath.Provider.LOGIN)
class LoginServiceRouter : ILoginService {
    override val accountId: String = "張三"
	.......
}
複製代碼

3.如今便可在mymodule模塊MeFragment中獲取登錄模塊的用戶Id

@Autowired
 @JvmField var loginService: ILoginService? = null
複製代碼

③基於事件總線

使用 LoacaBroadcastManage或者RxBus進行通訊

其餘約定

  • 實體類放在自己的 module 中是沒法傳遞的,能夠下沉,放到業務模塊下邊的providerservice中,或者在抽取一個datamodule類

  • 權限管理咱們將 normal 級別的權限申請都放到 Base module 中,而後在各個 module 中分別申請 dangerous 的權限 。 這樣分配的好處在於當添加或移除單一模塊時,隱私權限申請也 會跟隨移除 ,能作到最大程度的權限解禍 。不要將權限所有轉交到每一個 module 中,包括普通權限的聲明 ,由於這樣會增長 AndroidManifest的合併檢測的耗時’。

  • 組件化資源衝突

//一、AndroidMainfest 衝突問題
AndroidMainfest 中引用了 Application 的 app:nam巳 屬性 ,當出現衝 突 時, 須要使 用 tools:replace=」android:name」來聲明 Application 是可被替換 的 。
//二、依賴jar包衝突
當包衝突出現時,能夠先檢查依賴報告,使用命令 gradledependencies查看依賴目錄樹
//三、防止資源重複,resourcePrefix 這個值只能 限定 XML 中的資源,井不能限定圖片資源,全部圖片資源仍然須要手動去修改資源名 。
android {
resourcePrefix "紐件名」 } //組件化混淆,每一個module獨有的引用庫混淆放到各自 的 proguard-rule.pro 中 。 defaultConfig { ...... consumerProguardFiles 'proguard-rules.pro' } 複製代碼

代碼部署

多模塊能夠採用 git submodule\git subtree,或者上傳到 公司私服maven上統一管理。

源碼下載

相關文章
相關標籤/搜索