Demo Github地址
在Login模块的目录下面新建一个gradle.properties文件
#当为true时,表示作为一个单独的App运行,当为false时,表示作为一个库项目运行
asApp=false,
if(asApp.toBoolean()){
apply plugin: 'com.android.application'
}else {
apply plugin: 'com.android.library'
}
if (asApp.toBoolean()){
applicationId "com.haifeng.example.login"
}
public abstract class BaseApp extends Application {
/**
* Application 初始化
*/
public abstract void onCreateModuleApp(Application application);
}
class LoginApp :BaseApp(){
override fun onCreate() {
super.onCreate()
onCreateModuleApp(this)
}
override fun onCreateModuleApp(application: Application?) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
class MainApplication:Application(){
override fun onCreate() {
super.onCreate()
ARouter.openLog() // 打印日志
ARouter.openDebug() // 开启调
ARouter.init(this)
initModuleApp()
}
/**
* 初始化组件APP
*/
fun initModuleApp() {
for (moduleApp in AppConfig.moduleApps) {
try {
val clazz = Class.forName(moduleApp)
val baseApp = clazz.newInstance() as BaseApp
baseApp.onCreateModuleApp(this)
} catch (e: ClassNotFoundException) {
e.printStackTrace()
} catch (e: IllegalAccessException) {
e.printStackTrace()
} catch (e: InstantiationException) {
e.printStackTrace()
}
}
}
}
按照图片的示例新建一个manifest目录,然后分别创建一个app目录和一个lib目录,然后在这两个目录里面分别存放 作为app运行的清单文件和作为lib运行的清单文件,如下图所示
sourceSets {
main {
if (asApp.toBoolean()) {
manifest.srcFile 'src/main/manifest/app/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/manifest/lib/AndroidManifest.xml'
}
}
}
做完上面这些操作其实每个模块已经可以单独运行起来了,现在还需要解决一个问题,如果打包到主项目中,在gradle3.0的插件已经有实现了 runtimeOnly,在主项目的build.gradle的依赖中添加代码
dependencies {
runtimeOnly project(path: ':login')
}
runtimeOnly的意思是login这个模块在编译期间对app模块不可见,只在运行期间可见
这个问题其实在问题1已经有解决,这里主要解决一下资源冲突的问题
在login模块中的build.gradle中添加配置
resourcePrefix "login_"
resourcePrefix表示约束,加上这个配置后,login模块的所有资源必须以login_ 开头
这些资源文件包括,颜色,尺寸,layout等
如图,加上login_后编译成功,不加上则报错
组件化通信下面几个关键方式
Activity通信
Service通信
其他通信
关于Activity和Service通信方式可以参考Arouter,关于Aronter如何使用可以看看里面的文档
其他通信怎么实现?目前我想到了下面几种方式
广播和EventBus大家应该都比较熟悉,接下来我们重点介绍一下接口方式是怎么通信的
interface LoginApi{
fun showToast(toast:String)
}
class ApiService private constructor(){
var loginApi:LoginApi?= null
companion object{
val singleInstance:ApiService by lazy (mode = LazyThreadSafetyMode.SYNCHRONIZED){
ApiService()
}
}
fun showToast(toast:String){
loginApi?.showToast(toast)
}
}
ApiService 是一个单例,提供模块间基础服务的通信,所有的模块服务都需要在ApiService注册
class LoginApiImpl :LoginApi {
override fun showToast(toast: String) {
Toast.makeText(LoginApp.app,toast,Toast.LENGTH_SHORT).show()
}
}
override fun onCreateModuleApp(application: Application) {
app=application
ApiService.singleInstance.loginApi = LoginApiImpl()
}
组件化开发还有一个很关键的一个,保证依赖库的统一性,所以我们需要在根目录的build.gradle文件里面定义变量来控制依赖库
ext.versions = [
'minSdkVersion' : 15,
'targetSdkVersion': 28,
'versionCode' : 1,
'arouter_version' : '1.5.0',
'constraint_layout_version':'1.1.3',
'androidPlugin':'3.4.1'
]
ext.deps = [
//plugins
android : [
'gradlePlugin': "com.android.tools.build:gradle:${versions.androidPlugin}",
],
//google support
'support': [
'compat' : "com.android.support:support-compat:${versions.supportLibrary}",
'design' : "com.android.support:design:${versions.supportLibrary}",
'v7' : [
'appcompat' : "com.android.support:appcompat-v7:${versions.supportLibrary}",
'recyclerView': "com.android.support:recyclerview-v7:${versions.supportLibrary}",
'cardView' : "com.android.support:cardview-v7:${versions.supportLibrary}",
],
'v4' : [
'support_v4': "com.android.support:support-v4:${versions.supportLibrary}"
],
'annotations': "com.android.support:support-annotations:${versions.supportLibrary}",
'multidex' : "com.android.support:multidex:1.0.1",
'constraint' :"com.android.support.constraint:constraint-layout:1.1.3",
'test' : [
'runner': 'com.android.support.test:runner:1.0.1',
'rule' : 'com.android.support.test:rules:1.0.1'
],
],
]
在依赖中添加
implementation deps.support.compat.constraint