组件化思想
组件化对于各个领域都已经不是新鲜的词汇了,在Android上组件化已经遍地开花了,这里只是记录一下我对组件化的理解,有不对的地方请大家指出。
组件化是为了解决什么问题
优秀的工程项目应该满足高内聚低耦合思想,各个功能有明显的边界划分,各个模块各司其职,至少在修改的时候不是牵一发而动全身,其他人在接手的时候也能快速理解。
如果你的项目存在一下问题,可以考虑使用组件化了:
- 代码耦合严重,eventbus满天飞
- 依赖严重,编译慢
- 功能模块界限不清晰
- 多人开发的时候经常发生合并冲突
组件化的存在就是为了解决上述问题,将功能相关的作为一个单独模块,将经常使用的基础功能抽离出来作为基础模块,多人开发时每个人负责独立模块。
理想状态下,每个模块能进行独立开发、独立测试,在打包时合并为一个项目。
怎样使用组件化
大致分为以下步骤:
- 解决依赖问题
- 抽离公用模块
- 创建独立功能模块
- 模块间通信
我们的目的是搭建MVVM模式下的组件化框架,关于组件化的理论知识我们不做过多的介绍了。
参考:
www.jianshu.com/p/5e20a6740…
juejin.cn/post/688111…
搭建
解决依赖问题
组件化分为宿主App+多module,如果每个moduel都使用自己的依赖,那么管理起来相当费劲,不同module之间依赖的版本不同、升级都是问题,所以我们首先寻求的就是统一依赖管理
方式一:
在根目录下创建config.gradle文件,这个文件就是管理常用配置和依赖:
ext{
versions = [
compileSdkVersion: 29,
buildToolsVersion: "29.0.2",
minSdkVersion : 21,
targetSdkVersion : 29,
versionCode : 1,
versionName : "1.0"
]
// 组件化与集成化切换时,设置不同的applicationId
appId = [
app : "com.example.modular.todo",
shop: "com.example.modular.shop"
]
dependencies = [
appcompat : "androidx.appcompat:appcompat:${appcompatVersion}",
constraintlayout: "androidx.constraintlayout:constraintlayout:${constraintlayoutVersion}",
]
//这里只做实例
}
复制代码
然后再根目录的build.gradle中添加:
apply from: 'config.gradle'
复制代码
在不同的module模块中的引用:
// build.gradle
def supports = rootProject.ext.dependencies
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation supports.appcompat
implementation supports.constraintlayout
// supports 依赖
supports.each { key, value -> implementation value }
}
复制代码
还有一种buildSrc管理,我并不常用这种方式,更习惯下面这种:
最终实现方式
1. 新建moduel模块,名称为version
2. 将version模块的build.gradle修改为如下:
buildscript {
ext.kotlin_version = "1.5.20"
repositories {
google()
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'java-gradle-plugin'
repositories {
google()
mavenCentral()
}
dependencies {
implementation gradleApi()
implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
}
compileKotlin {
kotlinOptions {
jvmTarget = 1.8
}
}
compileTestKotlin {
kotlinOptions {
jvmTarget = 1.8
}
}
gradlePlugin {
plugins {
version {
// 在 app 模块需要通过 id 引用这个插件 ,修改为version模块包名
id = 'com.xlu.version'
// 实现这个插件的类的路径
implementationClass = 'com.xlu.version.VersionPlugin'
}
}
}
复制代码
在此模块下创建VersionPlugin
类,如下:
import org.gradle.api.Plugin
import org.gradle.api.Project
/**
* TODO 这里什么都不用做,创建就行了
*/
class VersionPlugin : Plugin<Project>{
override fun apply(target: Project) {
}
}
复制代码
3. 重要的一步:
- 打开工程根目录下的
setting.gradle
文件 - 删除原来的
include ':version'
- 修改为
includeBuild("version")
4. 在version模块下创建Dependency类,管理依赖
当然这个类名称自己随便起,实例如下:
object Dependency {
object ProjectConfig {
const val compileSdkVersion = 30
const val buildToolsVersion = "30.0.1"
const val applicationId = "com.example.mvvm_develop"
const val minSdkVersion = 16
const val targetSdkVersion = 30
const val versionCode = 1
const val versionName = "1.0"
const val isAppMode = false
}
object Version{
// Android---------------------------------------------------------------
const val Junit = "4.13"
const val Material = "1.2.0" // 材料设计UI套件
// AndroidX--------------------------------------------------------------
const val AppCompat = "1.2.0"
const val CoreKtx = "1.3.1"
const val ConstraintLayout = "2.0.1" // 约束布局
const val TestExtJunit = "1.1.2"
const val TestEspresso = "3.3.0"
const val ActivityKtx = "1.1.0"
const val FragmentKtx = "1.2.5"
const val MultiDex = "2.0.1"
// Kotlin----------------------------------------------------------------
const val Kotlin = "1.5.10"
const val Coroutines = "1.5.0" // 协程
// JetPack---------------------------------------------------------------
const val Lifecycle = "2.3.1" // Lifecycle相关(ViewModel & LiveData & Lifecycle)
const val Hilt = "2.35.1" // DI框架-Hilt
const val HiltAndroidx = "1.0.0"
}
object DependencyImp{
//Android
const val Junit = "junit:junit:${Version.Junit}"
const val Material = "com.google.android.material:material:${Version.Material}"
//AndroidX
const val AndroidJUnitRunner = "androidx.test.runner.AndroidJUnitRunner"
const val AppCompat = "androidx.appcompat:appcompat:${Version.AppCompat}"
const val CoreKtx = "androidx.core:core-ktx:${Version.CoreKtx}"
const val ConstraintLayout = "androidx.constraintlayout:constraintlayout:${Version.ConstraintLayout}"
const val TestExtJunit = "androidx.test.ext:junit:${Version.TestExtJunit}"
const val TestEspresso = "androidx.test.espresso:espresso-core:${Version.TestEspresso}"
const val ActivityKtx = "androidx.activity:activity-ktx:${Version.ActivityKtx}"
const val FragmentKtx = "androidx.fragment:fragment-ktx:${Version.FragmentKtx}"
const val MultiDex = "androidx.multidex:multidex:${Version.MultiDex}"
//Kotlin
const val Kotlin = "org.jetbrains.kotlin:kotlin-stdlib:${Version.Kotlin}"
const val CoroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Version.Coroutines}"
const val CoroutinesAndroid = "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Version.Coroutines}"
//Jetpack
const val ViewModel = "androidx.lifecycle:lifecycle-viewmodel-ktx:${Version.Lifecycle}"
const val ViewModelSavedState = "androidx.lifecycle:lifecycle-viewmodel-savedstate:${Version.Lifecycle}"
const val LiveData = "androidx.lifecycle:lifecycle-livedata-ktx:${Version.Lifecycle}"
const val Lifecycle = "androidx.lifecycle:lifecycle-runtime-ktx:${Version.Lifecycle}"
const val LifecycleCompilerAPT = "androidx.lifecycle:lifecycle-compiler:${Version.Lifecycle}"
const val HiltCore = "com.google.dagger:hilt-android:${Version.Hilt}"
const val HiltApt = "com.google.dagger:hilt-compiler:${Version.Hilt}"
const val HiltAndroidx = "androidx.hilt:hilt-compiler:${Version.HiltAndroidx}"
}
}
复制代码
上面代码应该很好理解吧,我们在上述创建好我们常用的依赖之后,就可以在其他modue中引用了。
上面类中的依赖在编译时并不会创建,只有在module中引用才会创建。
5. 其它module中使用
我们以宿主app模块为例,打开app模块的build.gradle文件
//setup1
import com.example.plugin.Dependency
// setup2
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.example.plugin' // 注意这里哦,不然上述的import会报错
}
复制代码
一些配置基础:
android {
compileSdkVersion Dependency.ProjectConfig.compileSdkVersion
buildToolsVersion Dependency.ProjectConfig.buildToolsVersion
defaultConfig {
applicationId Dependency.ProjectConfig.applicationId
minSdkVersion Dependency.ProjectConfig.minSdkVersion
targetSdkVersion Dependency.ProjectConfig.targetSdkVersion
versionCode Dependency.ProjectConfig.versionCode
versionName Dependency.ProjectConfig.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
......
}
复制代码
依赖管理:
dependencies {
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
//Android
api Dependency.DependencyImp.AppCompat
api Dependency.DependencyImp.Material
api Dependency.DependencyImp.AndroidXLeagcy
api Dependency.DependencyImp.ActivityKtx
api Dependency.DependencyImp.FragmentKtx
api Dependency.DependencyImp.MultiDex
//Kotlin
api Dependency.DependencyImp.Kotlin
api Dependency.DependencyImp.CoreKtx
//Kotlin协程核心库
api Dependency.DependencyImp.CoroutinesCore
api Dependency.DependencyImp.CoroutinesAndroid
//navigation
api Dependency.DependencyImp.NavigationFragment
api Dependency.DependencyImp.NavigationUI
//lifecycle
api Dependency.DependencyImp.Lifecycle
api Dependency.DependencyImp.Livedata
api Dependency.DependencyImp.Viewmodel
}
复制代码
具体参考Demo
上面可以看到我们用Dependency.ProjectConfig.xx这种方式代替了原来的数据,在Dependency类中统一管理
注意version所在的位置应该与Project处于同一层级,而不是与app module处于同一层级:
