Android 组件化设计

Android 组件化设计

什么是组件化

库 & 模块 & 组件 的区别:

  • 库:提供单一功能或一些功能。
  • 模块:指具体的业务逻辑模块,一个App可根据业务拆分为多个模块,如微信就定义了四个模块:微信、通讯录、发现、我。
  • 组件:指功能组件或业务组件,每个组件可以独立运行,功能组件如:视频组件、支付组件、数据组件等,业务组件如:登陆组件等。

组件化优点:

  • 在单工程项目中,各种业务代码混杂在一块,不方便后续的迭代、维护、调试,且代码复用性差。
  • 在组件化中,将App剥离开,分成多个模块,每个模块都是一个组件,一定程度上解决了代码的耦合问题,且组件是可以单独运行的,方便调试。

由此可见,模块和组件的最明显的区别是模块相对于组件来说粒度更大,一个模块可能包含多个组件。

在这里插入图片描述

开始组件化操作

自定义Gradle

定义一个config.gradle文件

ext {
    //独立运行组件开关
    isModule = false

    android = [
            compileSdkVersion    : 30,
            buildToolsVersion    : "30.0.3",
            minSdkVersion        : 21,
            targetSdkVersion     : 30,
            versionCode          : 1,
            versionName          : "1.0",
            applicationId        : "com.example.app",
            applicationId_chat   : "com.example.chat",
            applicationId_contact: "com.example.contact",
            applicationId_find   : "com.example.find",
            applicationId_me     : "com.example.me"
    ]

    dependencies = [
            //Kotlin
            "kotlin-stdlib"   : "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version",
            "core-ktx"        : 'androidx.core:core-ktx:1.3.1',
            //Android
            "appcompat"       : 'androidx.appcompat:appcompat:1.3.1',
            "material"        : 'com.google.android.material:material:1.2.1',
            "constraintlayout": 'androidx.constraintlayout:constraintlayout:2.0.1',
            //ARouter
            "arouter-api"     : 'com.alibaba:arouter-api:1.5.2',
            "arouter-compiler": 'com.alibaba:arouter-compiler:1.5.2',
            //CircleImageView
            "circleimageview" : 'de.hdodenhof:circleimageview:3.0.0',
            //ShapeView
            "shapeView"       : 'com.github.getActivity:ShapeView:8.0',
            //Eventbus
            "eventbus"        : 'org.greenrobot:eventbus:3.2.0'
    ]
}

并添加到项目下的build.gradle中

apply from: "config.gradle"

创建其他组件

通过 Flie -> New Module -> Android Library 依次创建:

在这里插入图片描述

配置app主工程

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion rootProject.ext.android["compileSdkVersion"]
    buildToolsVersion rootProject.ext.android["buildToolsVersion"]

    defaultConfig {
        applicationId rootProject.ext.android["applicationId"]
        minSdkVersion rootProject.ext.android["minSdkVersion"]
        targetSdkVersion rootProject.ext.android["targetSdkVersion"]
        versionCode rootProject.ext.android["versionCode"]
        versionName rootProject.ext.android["versionName"]
    }

    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'
    }

    //开启ViewBinding
    buildFeatures {
        viewBinding = true
    }
}

//ARouter
kapt {
    arguments {
        arg("AROUTER_MODULE_NAME", project.getName())
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation project(path: ':common')

    if (!Boolean.valueOf(rootProject.ext.isModule)) {
        implementation project(path: ':chat')
        implementation project(path: ':contact')
        implementation project(path: ':find')
        implementation project(path: ':me')
    }

    //ARouter
    implementation rootProject.ext.dependencies["arouter-api"]
    kapt rootProject.ext.dependencies["arouter-compiler"]
}

配置common组件

配置Gradle:

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion rootProject.ext.android["compileSdkVersion"]
    buildToolsVersion rootProject.ext.android["buildToolsVersion"]


    defaultConfig {
        minSdkVersion rootProject.ext.android["minSdkVersion"]
        targetSdkVersion rootProject.ext.android["targetSdkVersion"]
        versionCode rootProject.ext.android["versionCode"]
        versionName rootProject.ext.android["versionName"]
        consumerProguardFiles "consumer-rules.pro"
    }

    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'
    }
}

//ARouter
kapt {
    arguments {
        arg("AROUTER_MODULE_NAME", project.getName())
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    //Kotlin
    api rootProject.ext.dependencies["kotlin-stdlib"]
    api rootProject.ext.dependencies["core-ktx"]
    //Android
    api rootProject.ext.dependencies["appcompat"]
    api rootProject.ext.dependencies["material"]
    api rootProject.ext.dependencies["constraintlayout"]
    //ShapeView
    api rootProject.ext.dependencies["shapeView"]
    //CircleImageview
    api rootProject.ext.dependencies["circleimageview"]
    //Eventbus
    api rootProject.ext.dependencies["eventbus"]
    //ARouter
    implementation rootProject.ext.dependencies["arouter-api"]
    kapt rootProject.ext.dependencies["arouter-compiler"]
}

依次创建BaseApp、BaseActivity、BaseFragment等基类。

open class BaseApp : Application() {
    companion object {
        lateinit var context: Context
    }

    override fun onCreate() {
        super.onCreate()
        context = this
        if (BuildConfig.DEBUG) {
            ARouter.openLog()
            ARouter.openDebug()
        }
        ARouter.init(this)
    }
}

配置其他组件

这里以chat组件为例,其他都类似。

配置Gradle:

if (Boolean.valueOf(rootProject.ext.isModule)) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

android {
    compileSdkVersion rootProject.ext.android["compileSdkVersion"]
    buildToolsVersion rootProject.ext.android["buildToolsVersion"]

    defaultConfig {
        if (Boolean.valueOf(rootProject.ext.isModule)) {
            applicationId rootProject.ext.android["applicationId_chat"]
        }
        minSdkVersion rootProject.ext.android["minSdkVersion"]
        targetSdkVersion rootProject.ext.android["targetSdkVersion"]
        versionCode rootProject.ext.android["versionCode"]
        versionName rootProject.ext.android["versionName"]
    }

    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'
    }

    sourceSets {
        main {
            if (Boolean.valueOf(rootProject.ext.isModule)) {
                manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
            } else {
                manifest.srcFile 'src/main/AndroidManifest.xml'
                java {
                    //library模式下,排除java/debug文件夹下的所有文件
                    exclude '*module'
                }
            }
        }
    }

    //开启ViewBinding
    buildFeatures {
        viewBinding = true
    }
}

//ARouter
kapt {
    arguments {
        arg("AROUTER_MODULE_NAME", project.getName())
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation project(path: ':common')

    //ARouter
    implementation rootProject.ext.dependencies["arouter-api"]
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
    kapt rootProject.ext.dependencies["arouter-compiler"]
}

配置manifest文件:

在这里插入图片描述

src/main/AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.chat">

    <application>
        <activity
            android:name=".RunChatActivity"
            android:label="RunChatActivity" />
        <activity android:name=".info.ChatInfoActivity" />
        <activity android:name=".MyFragmentActivity" />
    </application>

</manifest>
src/main/manifest/AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.chat">

    <application
        android:name=".base.ChatApp"
        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.App">
        <activity android:name=".RunChatActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".info.ChatInfoActivity" />
        <activity android:name=".MyFragmentActivity" />
    </application>

</manifest>

使用ARouter组件间跳转

定义跳转路径

Path路径至少是两个层级,同一组件第一级路径不能重复。

object ARouterConstant {
    //chat组件
    const val PATH_CHAT_RUN = "/Chat/RunChatActivity"

    //contact组件
    const val PATH_CONTACT_RUN = "/contact/RunContactActivity"
    const val PATH_CONTACT_MY_ACTIVITY = "/contact/MyActivity"

    //find组件
    const val PATH_FIND_RUN = "/find/RunFindActivity"
    const val PATH_FIND_FRAGMENT = "/find/FindFragment"

    //me组件
    const val PATH_ME_RUN = "/me/RunMeActivity"

}

注册

@Route(path = ARouterConstant.PATH_CHAT_RUN)
class RunChatActivity : BaseActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_run_chat)
    }
}

跳转

ARouter.getInstance().build(ARouterConstant.PATH_CHAT_RUN).navigation()

组件间通信

  • EventBus
  • 广播

资源冲突问题

最终所有组件都会合并在一起,为了防止资源重名问题,在项目下的build.gradle中定义一个前缀:

//资源冲突
subprojects {
  afterEvaluate {
    android {
      resourcePrefix "${project.name}_"
    }
  }
}

添加前缀后,AS会约束我们在定义资源名时,但仍然需要我们手动添加上,对图片资源不会提示。

代码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值