背景
组件化已经流行多年了,大部分团队的组件化,还是部分的组件化,比如Activity,Fragment,Res,Androidmanifaset资源的module化隔离,但是,针对有些初始化必须在Application里做的,基本上,还是需要写在App模块下的application里,就会导致App模块下的appcation里臃肿,且,增加了非必要性的引用,这里呢,提供了一套完全彻底化组件化方案,组件Module也可以有自己的Application,一个应用在启动的使用,只有一个Application会被启动,那么组件module的Application如何被启动从而调用里面的初始化代码呢?继续往下看:
?第一、首先在BaseLibrary组件种定义一个BaseApplication,所有application都继承该类、如下:
class MyBaseApplication : Application() {
var moduleApps = ArrayList<Application>()
//依次调用组件的Application onCreate
override fun onCreate() {
super.onCreate()
moduleApps.forEach { it.onCreate() }
}
override fun attachBaseContext(base: Context?) {
super.attachBaseContext(base)
initModuleApplication()
}
//反射创建组件Application
private fun initModuleApplication() {
if (BaseInit.con != null)
return
BaseInit.init(this)
var info = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
if (info.metaData == null)
return
var apps = info.metaData.keySet()
apps.forEach {
try {
var cla = Class.forName(it.toString())
var app = cla.newInstance()
if (app is Application && cla.name != this::class.java.name) {
initModuleAppAttach(app)
}
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
}
}
//反射对组件Application进行初始化调用
private fun initModuleAppAttach(app: Application) {
val method: Method? = Application::class.java.getDeclaredMethod("attach", Context::class.java)
if (method != null) {
method.isAccessible = true
method.invoke(app, baseContext)
moduleApps.add(app)
}
}
}
?第二、在【组件】Module种定义组件的Application继承自MyBaseApplication,并在onCreate中写上需要初始化就调用的代码:
class AccountApplication : MyBaseApplication() {
override fun onCreate() {
super.onCreate()
log("AccountApplication onCreate ....账号Module的Application被调用了")
}
}
第三、在【组件】Module中的AndroidManifast.xml声明该组件下的Application,如下:
<application
android:name=".AccountApplication"
android:allowBackup="true"
android:icon="@mipmap/base_ic_launcher"
android:label="@string/a_app_name"
android:supportsRtl="true"
android:theme="@style/Theme.BASE">
<meta-data
android:name="com.chenliang.account.AccountApplication"
android:value="com.chenliang.account.AccountApplication" />
</application>
1、android:name=".AccountApplication"声明该module的自定义Application,当该Module是可独立运行的application的时候,该Application会被直接启动
2、<meta-data />添加对自定义application的声明name和value必须是该application的包名全称。
?原理说明:
1、在整个app在编译打包合并的时候,各个组件的Androidmanifest.xml会合并到主App的Androidmanifest.xml,子组件中声明的自定义applicaiton会被主App的Application replace掉(主app androidmanifast.xml配置:tools:replace="icon,label,theme,name"),而各个组件中在meta-data中声明的组件的application会合并到主androidmanifast.xml中。
2、主Application启动时,会调用BaseApplication中的initModuleApplication方法,该方法会解析androidmanifast.xml中所有<meta-data/>的value值,并通过该value值 反射来创建实例,如果该实例是Application的子类,则在initModuleAppAttach内通过反射调用该实例的attach方法进行初始化,并把该实例放入moduleApps集合中,在主Application调用到onCreate时,会对moduleApps中的application实例依次调用onCreate方法,从而达到,子module组件中Application的初始化操作。
3、到此,整个Application的组件化方案就说完了,在整个初始化过程中,各自组件的Application是相互独立的,没有App对组件module中初始化调用的任何引用,从而达到了,组件可以快速集成到主app中,也可以快速从主app拆解出来。
查看组件化实现方案项目,请查看具体代码,记得给个星:
https://github.com/chenliangj2ee/Android-MVVM-Component-Jetpack-Kotlin
????????
|