Android 组件化

1.组件化的优势
Android APP组件化架构的目标:告别结构臃肿,让各个业务变得相对独立,业务组件在组件模式下可以独立开发,而在集成模式下又可以变为arr包集成到“app壳工程”中,组成一个完整功能的APP;从组件化工程模型中可以看到,业务组件之间是独立的,没有关联的,这些业务组件在集成模式下是一个个library,被app壳工程所依赖,组成一个具有完整业务功能的APP应用,但是在组件开发模式下,业务组件又变成了一个个application,它们可以独立开发和调试,由于在组件开发模式下,业务组件们的代码量相比于完整的项目差了很远,因此在运行时可以显著减少编译时间。

2.组件化项目架构详解

image.png

左图是项目组件化工程模型

集成模式: 所有的业务组件被“app壳工程”依赖,组成一个完整的APP;

组件模式: 可以独立开发业务组件,每一个业务组件就是一个APP;

app壳工程: 负责管理各个业务组件,和打包apk,没有具体的业务功能;

业务组件: 根据公司具体业务而独立形成一个个的工程;

Main组件:属于业务组件,指定APP启动页面、主界面 ;

Common组件: 也就是功能组件(component_base 模块),支撑业务组件的基础,提供多数业务组件需要的功能,例如提供网络请求功能;

component_data组件: 存放与项目相关的公共数据,例如bean的基类,IntentKV存数据的键值对等.

SDK组件: 集成微信,支付宝支付,分享,推送等常用的第三方框架.

3.项目中实践

image.png
3.1.kotlin+MVP+组件化对项目框架搭建

View:UI层,显示数据,并且向Presenter层报告用户行为

Model:数据层,负责与网络层、数据库层逻辑交互

Presenter:从Model拿数据应用到UI层管理UI状态,决定显示什么,响应用户行为

3.2组件化划分详情

image.png
3.3项目目录划分

image.png
4.组件化搭建流程
4.1组件模式和集成模式切换的实现:
4.1.1 config.gradle文件增加变量配置
ext {

isMineApplication = false  //HomeModule开关,false:作为Lib组件存在, true:作为application存在
isHomeApplication = false  //MineModule开关,false:作为Lib组件存在, true:作为application存在
isMessageApplication = false //MessageModule开关,false:作为Lib组件存在, true:作为application存在
isPrepareLessonApplication = false // PrepareLessonModule开关,false作为Lib组件存在,true:作为application存在
复制代码

}
4.1.2组件模式和集成模式切换的实现(每个业务模块gradle配置如下):
if (rootProject.ext.isPrepareLessonApplication) {
apply plugin: ‘com.android.application’
} else {
apply plugin: ‘com.android.library’
}
4.1.3组件之间AndroidManifest合并:
在 Android中每一个组件都会有对应的 AndroidManifest.xml,用于声明需要的权限、Application、Activity、Service、Broadcast等,当项目处于组件模式时,业务组件的 AndroidManifest.xml 应该具有一个 Android APP 所具有的的所有属性,尤其是声明 Application 和要 launch的Activity,但是当项目处于集成模式的时候, 我们要为组件开发模式下的业务组件再创建一个AndroidManifest.xml,然后根据isModule指定AndroidManifest.xml的文件路径,让业务组件在集成模式和组件模式下使用不同的AndroidManifest.xml。

sourceSets {
main {
if (rootProject.ext.isPrepareLessonApplication) {
manifest.srcFile ‘src/main/module/AndroidManifest.xml’
} else {
manifest.srcFile ‘src/main/AndroidManifest.xml’
}
jniLibs.srcDirs = [‘libs’]
}
}
4.1.4单独业务组件Application独立初始化问题:
当部分模块有特有功能时候,有些初始化操作需要在某个模块的Application的onCreate中做初始化操作:

此处举例我们项目中的个人中心模块(MineMoudle)需要单独对智齿sdk做初始化操作我们不可能写在Library的BaseApplication去做初始化操作,如果在BaseApplication中去做初始化操作当我们打包其中某一个业务模块时(不使用智齿sdk的业务的模块)此时的BaseApplication如果做初始化智齿sdk的操作是不合理的。解决方案如下:

在BaseApplication的onCreate方法中调用如下方法(反射+多态思想实现单独模块的初始化方法调用):

/**

  • 初始化各个Module单独需要在Application中初始化的业务
  • 每个组件的BaseApplicationImp都需要将绝对
  • 路径存储到ModuleConfig.MODULELIST中以便通过反射初始化
  • 进而调用onCreate进行单独module的初始化

*/
private fun initModuleConfig() {
ModuleConfig.MODULE_PATH_LIST.forEach { moduleImpl ->
try {
val clazz = Class.forName(moduleImpl)
val obj = clazz.newInstance()
if (obj is BaseApplicationImp) {
obj.onCreate(this)
}
} catch (e: ClassNotFoundException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
} catch (e: Fragment.InstantiationException) {
e.printStackTrace()
}
}
}
ModuleConfig.MODULE_PATH_LIST 配置如下
interface ModuleConfig {
companion object {
val MODULE_APP = “com.tal.firstleap.app.AppImp”
val MODULE_MINE = “com.tal.minemodule.app.MineModuleAppImp”
val MODULE_HOME = “com.tal.homemodule.app.HomeModuleAppImp”

    val MODULE_PATH_LIST = arrayOf(MODULE_APP,MODULE_MINE, MODULE_HOME)
}
复制代码

}
其中的MODULE_PATH_LIST常量存储的是在某个module重的BaseApplicationImp接口实现类的绝对路径

interface BaseApplicationImp {
fun onCreate(application:Application)
}

MineModuleAppImp存在于某一个需要的业务组件
class MineModuleAppImp : BaseApplicationImp {

//做此Module的Application中需要初始化的业务
override fun onCreate(application: Application) {
    //参数3 用户的唯一标识,不能传一样的值,可以为空
    SobotApi.initSobotSDK(application, Constant.SABOT_APP_KEY,"")
}
复制代码

}
4.1.5组件间通信
使用了阿里Arouter实现页面跳转以及数据传递,详情如下
github.com/alibaba/ARo…

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享