美文网首页程序员
android组件化之路

android组件化之路

作者: flywfk | 来源:发表于2017-03-06 23:13 被阅读685次

    问题:实际业务变化快,而工程内各个功能模块耦合度太高,不能对功能模块进行快速方便地拆分或组装。团队共同开发中,可能一个文件同时被多人修改,导致每次更新提交代码都需要消耗大量时间去merge代码。每次修改,都需要进行功能测试和系统测试。

    目的:解决以上问题,使项目可以灵活配置,功能模块完全解耦,实践组件化之路。

    实现:在之前的开发中,一个应用程序,我们将全部功能模块都写在工程app包中。实践组件化,我们将各个功能模块独立出来,最终以依赖包的形式整合到app主Module中去。在这里我写了个项目demo,简单分了几个功能模块,应用结构如下图所示:

    项目组件化结构图

    说明:每一个组件module是一个子工程,子工程可以依赖基础库baselibrary可独立运行;也可以作为主工程的依赖库。

    具体实现:1:配置项目的buildscript,如下图所示:

    buildscript配置

    关于butterknife的配置及用法:http://jakewharton.github.io/butterknife,butterknife8支持在lib库中注解。

    2:在主app module gradle中如下配置:

    applyplugin:'com.android.application'

    applyplugin:'android-apt'

    android {

        compileSdkVersion COMPILE_SDK_VERSION as int

        buildToolsVersion BUILD_TOOLS_VERSION

        defaultConfig {

            applicationId APPLICATION_ID

            minSdkVersion MIN_SDK_VERSIONas int

            targetSdkVersion TARGET_SDK_VERSIONas int

            versionCode 1

            versionName "1.0"

        }

        signingConfigs {

            debugConfig {

                storeFile file("***.jks")

                storePassword "******"

                keyAlias "*****"

                keyPassword "******"

            }

        releaseConfig {

            storeFile file("******.jks")

            storePassword "********"

            keyAlias "*****"

            keyPassword"*******"

        }

    }

    }

     buildTypes {

           release {

             minifyEnabled false

             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

         }

      }

    dependencies {

    if(!isDebug.toBoolean()) {//各个模块作为库加载

    compile project(':loginmodule')

    compile project(':startmodule')

    compile project(':homemodule')

    compile project(':msgmodule')

    }else{//各模块独立运行

    compile project(':baselibrary')

    }

    //router

    apt'com.github.mzule.activityrouter:compiler:1.1.7'

    }

    说明:关于activityrouter的配置及使用,在后面会说到。

    3:baselibrary作为各个模块共同依赖的基础库,其gradle配置如下:

    applyplugin:'com.android.library'

    applyplugin:'com.jakewharton.butterknife'

    applyplugin:'android-apt'

    android {

    compileSdkVersion24

    buildToolsVersion"25.0.2"

    defaultConfig {

    minSdkVersion15

    targetSdkVersion24

    versionCode1

    versionName"1.0"

    }

    buildTypes {

    release {

    minifyEnabledfalse

    proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'

    }

    }

    }

    dependencies {

    compile fileTree(include: ['*.jar'],dir:'libs')

    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {

    excludegroup:'com.android.support',module:'support-annotations'

    })

    compile'com.android.support:appcompat-v7:24.2.1'

    compile'com.jakewharton:butterknife:8.5.1'

    apt'com.jakewharton:butterknife-compiler:8.5.1'

    compile'com.github.mzule.activityrouter:activityrouter:1.2.2'

    }

    4:在子工程模块gradle配置如下(以homemodule为例):

    if(isDebug.toBoolean()) {

    applyplugin:'com.android.application'

    }else{

    applyplugin:'com.android.library'

    }

    applyplugin:'com.jakewharton.butterknife'

    applyplugin:'android-apt'

    android {

    compileSdkVersion24

    buildToolsVersion"25.0.2"

    defaultConfig {

    minSdkVersion15

    targetSdkVersion24

    versionCode1

    versionName"1.0"

    testInstrumentationRunner"android.support.test.runner.AndroidJUnitRunner"

    }

    buildTypes {

    release {

    minifyEnabledfalse

    proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'

    }

    }

    sourceSets {

    main{

    if(isDebug.toBoolean()) {

    manifest.srcFile'src/debug/AndroidManifest.xml'

    }else{

    manifest.srcFile'src/release/AndroidManifest.xml'

    }

    }

    }

    resourcePrefix"home_"

    }

    dependencies {

    compile fileTree(dir:'libs',include: ['*.jar'])

    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {

    excludegroup:'com.android.support',module:'support-annotations'

    })

    compile project(':baselibrary')

    apt'com.jakewharton:butterknife-compiler:8.5.1'

    //router

    apt'com.github.mzule.activityrouter:compiler:1.1.7'

    }

    说明:当module单独运行和作为module运行时,其activity在manifest中设置也会不同,这里可以根据isDebug设置不同的manifest。当分别开发模块时,容易出资源重复命名的问题,可以在build.gradle中设置resourcePrefix "home_",通过给模块设置不同的资源前缀,可以避免重复命名。

    Activity跳转问题

    从上面的配置中,可以看到,项目引入了apt'com.github.mzule.activityrouter:compiler:1.1.7',我们为什么使用ActivityRouter呢,当我们把各个功能模块抽成独立的lib的时候,各个模块之间难免要进行Activity的跳转及传参。我们不能再像以前那样直接通过startActivity来实现跳转了。关于ActivityRouter的配置及用法:https://github.com/mzule/ActivityRouter

    使用在application中注解:@Modules({"app","homeModule","loginModule","startModule","msgModule"})

    public class XxxxApplication extends Application {

    }

    每个module中创建空java类注解:

    @Module("homeModule")

    public class HomeModule{

    }

    组件间通信问题:

    不同组件Activity之间传递大量数据时可以通过EventBus来进行传递,EventBus原理及用法:https://github.com/greenrobot/EventBus

    编译运行

    当在gradle.properties中设置isDebug=true时,可以独立运行每个module,独立运行调试,当设置isDebug=false,可以编译运行整个project,注意isDebug变量设置改变时,要重新对gradle进行sync。

    可能遇到的一些问题:

    1:如果遇到/com/github/mzule/activityrouter/router/RouterInit.java javaError:(7, 5) 错误: 找不到符号 符号:  变量 RouterMapping等错误,请检查app是否把各个Module都依赖进来了。

    2:使用butterknife注解时,每个Module会对应生成R2文件,即使在base库里注解过了,Module也要重新注解,组件中不能直接使用。

    3:如果项目中使用到menu注意:

    @Override

    protected void onMenuItemClick(MenuItem item) {

    //        switch (item.getItemId()) {

    //            case R2.id.xxx:

    //                Routers.open(mContext,"");

    //                break;

    //        }

    if (item.getItemId() == R.id.xxx){

    Routers.open(mContext,"");

    }

    super.onMenuItemClick(item);

    }

    寻找对应的menu id时,用if else 代替 switch,注:itemid 和 R2值不一样,和R是一样的。

    相关文章

      网友评论

        本文标题:android组件化之路

        本文链接:https://www.haomeiwen.com/subject/rptbmttx.html