写一个MVVM快速开发框架(二)组件化改造

组件化思想

组件化对于各个领域都已经不是新鲜的词汇了,在Android上组件化已经遍地开花了,这里只是记录一下我对组件化的理解,有不对的地方请大家指出。

组件化是为了解决什么问题

优秀的工程项目应该满足高内聚低耦合思想,各个功能有明显的边界划分,各个模块各司其职,至少在修改的时候不是牵一发而动全身,其他人在接手的时候也能快速理解。

如果你的项目存在一下问题,可以考虑使用组件化了:

  1. 代码耦合严重,eventbus满天飞
  2. 依赖严重,编译慢
  3. 功能模块界限不清晰
  4. 多人开发的时候经常发生合并冲突

组件化的存在就是为了解决上述问题,将功能相关的作为一个单独模块,将经常使用的基础功能抽离出来作为基础模块,多人开发时每个人负责独立模块。

理想状态下,每个模块能进行独立开发、独立测试,在打包时合并为一个项目。

怎样使用组件化

大致分为以下步骤:

  1. 解决依赖问题
  2. 抽离公用模块
  3. 创建独立功能模块
  4. 模块间通信

我们的目的是搭建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处于同一层级:

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享