解决组件化中 ModuleApplication 共存问题

一个美好的设想

组件化的目的是为了业务解耦,每一个业务模块须要不一样的功能,例如车辆详情模块须要第三方分享,城市定位模块须要百度地位等。有些特殊功能的初始化须要在 Application 中去作,可是这些功能并不是所有业务组件都用到的东西,放到 BaseApplication 不合适。android

所以,我想这样操做:git

  • 模块共有的初始化,放入BaseApplication 中。
  • 模块自身的特殊功能初始化,放在本身的 Application。

设想是美好的,但实现前须要先思考一个问题:github

多 Module 项目开发的时候,app module 和 library module 的 都有不一样的自定义 Application ,能够共存而且自动合并吗?bash

答案是 No。微信

为何不能够?

首先,自定义 Application 须要声明在 AndroidManifest.xml 中。其次,每一个 Module 都有该清单文件,可是最终的 APK 文件只能包含一个。所以,在构建应用时,Gradle 构建会将全部清单文件合并到一个封装到 APK 的清单文件中。app

合并的优先级是:ide

App Module > Library Module工具

合并的规则:组件化

结合咱们的状况,是值 A 合并值 B,会产生冲突错误,以下是个人亲身试法:post

Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed : Attribute application@name value=(com.baseres.BaseApplication) from AndroidManifest.xml:8:9-51
  	is also present at [:carcomponent] AndroidManifest.xml:14:9-55 value=(com.carcomponent.CarApplication).
  	Suggestion: add 'tools:replace="android:name"' to <application> element at AndroidManifest.xml:7:5-24:19 to override.

复制代码

错误信息中给出了解决建议,在高优先级的 App Module 中使用 tools:replace="android:name",但这样作是直接用值 A 替换了值 B,并不是咱们想要的结果。

除了上面报错的方法,另外再推荐给你们一个方法,打开 App Module 的 AndroidManifest.xml 文件,选择下方 Merged Manifest 选项卡,能够看到预合并结果。

以上咱们就明白为何不一样的 Application 不能共存的缘由。那还有其余方法去实现美好设想吗?

此次的答案是 Yes !

强烈感谢反射的存在

回想需求来源,是须要在 Application 建立时期,实现模块的特殊功能初始化,初始化时间和初始化内容 是肯定无误,问题核心是如何链接二者。直接链接方式实践失败,只能采用间接方式。一提到间接,因而想起来了反射。

  • 初始化内容,假设如今写在 ModuleA 的 A 类,ModuleB 的 B 类中的 init() 方法中。
  • 最终 Application 的 onCreate 中经过反射拿到 A 类 和 B 类,调用各自的 init() 方法。

以上就已经解决咱们的问题,可是为了 A 类 和 B 类 中的初始化方法名称保持一致,最好使用接口强制规范。建立接口 IComponentApplication,其中定义好方法签名,让 A 类和 B 类都实现它。如此,接口应放在 基础库 BaseRes 中,反射调用内容放在 BaseApplication 最为合适。

全部的思惟逻辑演变成代码是这样纸的:

Module A:

private class A implements IComponentApplication{

	public void init(Application application){
	   // ModuleA的初始化
	}
	
}

Module B:

private class B implements IComponentApplication{

	public void init(Application application){
	   // ModuleB的初始化
	}
	
}


BaseRes 中:

public interface IComponentApplication {

	void init(Application application);

}

public class MyApplication extends Application {
	private static final String[] MODULESLIST =
	              {"com.moduleA.A",
	              "com.moduleA.B"};
	
	@Override
	public void onCreate() {
		super.onCreate();
	
		//Module类的APP初始化
		modulesApplicationInit();
	}
	
	private void modulesApplicationInit(){
		 for (String moduleImpl : MODULESLIST){
		     try {
		         Class<?> clazz = Class.forName(moduleImpl);
		         Object obj = clazz.newInstance();
		         if (obj instanceof IComponentApplication){
		             ((IComponentApplication) obj).init(BaseApplication.getInstance());
		         }
		     } catch (ClassNotFoundException e) {
		         e.printStackTrace();
		     } catch (IllegalAccessException e) {
		         e.printStackTrace();
		     } catch (InstantiationException e) {
		         e.printStackTrace();
		     }
		  }
	}
}

复制代码

最后有福利

福利是组件化系列博客所说的方案,写出来了一个Demo,传送门在这里 大家可能须要的组件化 Demo。说是福利,大概是个人脸太大,技术浅薄,欢迎指正和交流。

另外,关于 AndroidManifest.xml 的合并,详细了解能够看这里合并多个清单文件 Google 官方文档,须要自备交通工具。

最后是个人组件化系列文章,内容简单易懂,但愿对你能有所帮助:

是什么让我开始了组件化?

解决组件化中 ModuleApplication 共存问题

下篇文章见。

欢迎关注博主的微信公众号,快快加入哦,期待与你一块儿成长!

欢迎关注博主的微信公众号,快快加入,期待与你一块儿成长!
相关文章
相关标签/搜索