Android组件化开发笔记
Modularization
什么是组件化
组件化就是将一个app拆分成不同的组件,每一个组件都是一个独立的module。
组件化的意义
组件化能降低耦合性,而耦合性低就能提高维护性。
于此同时由于组件间是独立的,所以组件与组件间耦合性低,所以我们在团队开发的时候可以以组件为分割单位,这样就能提高开发效率。
如何进行组件化
组件化是依靠gradle实现的。所以不会gradle的得去学学基础语法。当然也可以不学,只是说看别人写的代码看的半懂不懂的。
第一步创建Module
起点是一个全新的Project
创建Module有好几种方法。
右击new Module
这个得注意位置哦,不然new出来全在app包下不是很好,通常我们的module是和app平级的。也就是说在大project下面。
在我的这个demo中就是Modularization下面
点击File new一个Module
这里我创建了3个module,一个lib
注意命名,module是module_模块名,lib是lib__库名称.
简单区分以下module和lib,lib就是不显示页面的模块,module就是一个页面模块的集合。
将版本信息配置到一个gradle文件中
Tips:
fileName :app_versions.gradle
//applicationIds
def appIds = [:]
appIds.module_main = "com.example.module_main"
appIds.module_one = "com.example.module_one"
appIds.module_two = "com.example.module_two"
appIds.app = "com.example.modularization"
ext.appIds = appIds
将该gradle文件配置到project的build.gradle中
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
apply from: 'app_versions.gradle'
ext{
app_configs = "$rootDir/app_config.gradle"
}
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
配置gradle的编译插件
先在gradle.properties,加入一个变量判断是否是发行状态
组件化中有两种状态,一种是debug状态,一个是发行状态,
- debug状态也就是开发阶段,这个阶段每一个模块都是一个独立的app,可以独立运行
- release发行状态,这个状态下只有app模块可以独立运行,其他的模块都是lib,依托于app模块。
然后创建了一个app_config.gradle文件
编写代码使得module_XX能在lib和app中切换状态。
这里有一点需要注意我们在gradle.propergies虽然写了一个isRelease的bool变量但是其实gradle这里获取的是一个string,得用toBoolean()进行转化。
if (isRelease.toBoolean()){
if (project.name != 'app') apply plugin: 'com.android.library'
else apply plugin: 'com.andorid.application'
}
else{
if (project.name.matches('module_.+') || project.name == 'app') apply plugin: 'com.android.application'
else if (project.name.matches('lib_.+')) apply plugin: 'com.android.library'
}
然后加入必要的依赖
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
配置Manifest文件
android{
`````
sourceSets{
main{
if (isRelease.toBoolean()){
manifest.srcFile "src/main/AndroidManifest.xml"
}else {
if (project.name.matches('module_.+')){
manifest.srcFile "src/main/manifest/AndroidManifest.xml"
}else if (project.name.matches('lib_.+') || project.name == 'app'){
manifest.srcFile "src/main/AndroidManifest.xml"
}
}
}
}
`````
}
然后对module的manifest文件进行一点变动
在main文件夹下创建manifest文件夹,然后把debug状态的manifest的文件放进去。
debug状态下的文件(这个状态下编译的文件是apk所以需要配置启动页和一些application的选项)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.module_main">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Modularization">
<activity
android:name=".MainMainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
release状态下的manifest文件(这个状态下的编译文件是aar文件所以只需要注册一个activity,其余的都不需要)
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.module_main">
<application>
<activity
android:name=".MainMainActivity"
android:exported="true" />
</application>
</manifest>
其余的module_XX,模块也是按照这样改。
配置applicationId
由于application才有applicationId,所以lib是没有applicationId的,而module在application和module之间疯狂切换,说以是有必要进行设置的。
if (isRelease.toBoolean()) {
applicationId "com.example.modularization"
}else {
if (project.name.matches('module_.+') || project.name == 'app') {
applicationId appIds[project.name]
}
}
之后在project的build.gradle中加点变量方便其gradle文件访问app_config.gradle文件(注意要加等号‘=’)
buildscript {
ext{
app_config = "$rootDir/app_config.gradle"
}
repositories {
google()
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.0"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
module引用app_config.gradle
之前
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdk 30
defaultConfig {
applicationId "com.example.module_main"
minSdk 21
targetSdk 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
之后
apply from: app_configs
dependencies {
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
其余的lib和module都是这样
把android闭包下的一些属性进行抽离
def android_versions = [:]
android_versions.sdk_version = 30
android_versions.min_version = 21
android_versions.target_version = 30
android_versions.version_code = 1
android_versions.version_name = "1.0"
def kotlin_options = [:]
kotlin_options.jvm_target = '1.8'
android_versions.kotlin_options = kotlin_options
ext.android_versions = android_versions
app_config.gradle的内容
if (isRelease.toBoolean()){
if (project.name != 'app') apply plugin: 'com.android.library'
else apply plugin: 'com.andorid.application'
}
else{
if (project.name.matches('module_.+') || project.name == 'app') apply plugin: 'com.android.application'
else if (project.name.matches('lib_.+')) apply plugin: 'com.android.library'
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android {
compileSdk android_versions.sdk_version
defaultConfig {
if (isRelease.toBoolean()) {
applicationId "com.example.modularization"
}else {
if (project.name.matches('module_.+') || project.name == 'app') {
applicationId appIds[project.name]
}
}
minSdk android_versions.min_version
targetSdk android_versions.target_version
versionCode android_versions.version_code
versionName android_versions.version_name
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
sourceSets{
main{
if (isRelease.toBoolean()){
manifest.srcFile "src/main/AndroidManifest.xml"
}else {
if (project.name.matches('module_.+')){
manifest.srcFile "src/main/manifest/AndroidManifest.xml"
}else if (project.name.matches('lib_.+') || project.name == 'app'){
manifest.srcFile "src/main/AndroidManifest.xml"
}
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = android_versions.kotlin_options.jvm_target
}
}