组件化Android开发经验谈Flutter

android 组件化重构项目

2019-07-18  本文已影响23人  刘景昌

1.为什么要组件化

(1)耦合严重:单一工程的业务之间耦合度太高,牵一发而动全身
(2)编译时间慢: 对工程的任何更改都必须编译整个工程
(3)测试麻烦:功能测试和系统测试每次都要进行
(4)开发效率不高:共同开发时容易产生冲突
(5)不够灵活:不能灵活的对业务模块进行配置和组装;

2.组件化介绍

组件化就是一个完整的app拆分成多个子模块每个子模块可以独立的编译或者运行,可以任意组合成另一个新的app或者模块,每个模块之间几部想不依赖有可以相互交互 。
组件化的基本组成:
(1)app壳工程:就是一个空的工程,负责打包apk没有具体的业务功能
(2)业务组件:每个业务模块单独出来可以形成一个独立的工程
(3)common组件:为每个业务模块提供公共的组件 如 工具类 网络类的封装
(4)三方组件:把一系列的三方类的功能集合在一起形成的组件 如 微信支付+支付宝支付 +其他三方支付= 支付组件

3.组件化实施流程

由于是之前自己独立开发的一个比较小的工程,所有逻辑也是自己写的所以实施组件化起来还是比较方便的,因为是重构以前的工程而不是重写 所以需要一步步的进行 从开始学习开始 到最后的组件化完成 差不多一周时间 。
(1)拆解工程 提取commonLibrary模块
我们在提取过程中要做的事情

1.为了保证每个业务组件的版本的统一个模块是否模块化的开启

添加统一的引用的gradle config.gradle 在这里吧原来使用的引用和版本都添加进来

/**
 *  全局统一配置文件
 */
ext {
    //true 每个业务Module可以单独开发
    //false 每个业务Module以lib的方式运行
    //修改之后需要Sync方可生效
    isModule = false
    //版本号
    versions = [
            applicationId           : "com.example.componentapplication",        //应用ID
            versionCode             : 1,                    //版本号
            versionName             : "1.0.0",              //版本名称

            compileSdkVersion       : 28,
            buildToolsVersion       : "28.0.3",
            minSdkVersion           : 17,
            targetSdkVersion        : 23,

            androidSupportSdkVersion: "28.0.0",
            constraintLayoutVersion : "1.1.1",
            runnerVersion           : "1.0.1",
            espressoVersion         : "3.0.1",
            junitVersion            : "4.12",
            annotationsVersion      : "24.0.0",
            javaSDKVersion          : 1.8,//javaSDK版本

            multidexVersion         : "1.0.2",
            butterknifeVersion      : "9.0.0",

            arouterApiVersion       : "1.4.0",
            arouterCompilerVersion  : "1.2.1",
            arouterannotationVersion: "1.0.4",
            gsonVersion             :"2.4",
            //rxjava 家族和网络请求
            rxjavaVersion           :"2.1.6",
            rxandroidVersion        :"2.0.1",
            retrofitVersion         :"2.3.0",
            convertergsonVersion    :"2.2.0",
            rxjava2adapterVersion   :"2.3.0",
            logginginterceptorVersion:"3.7.0",
            takephotolibraryVersion :"4.0.3" ,
            glideVersion            :"3.8.0",
            baservadapterVersion    :"3.0.3",
            flowlayoutVersion       :"1.0.3",
            permissionVersion       :"1.1.0",
            autosizeVersion         :"1.1.2"

    ]
    dependencies = [
            "appcompat_v7"        : "com.android.support:appcompat-v7:${versions["androidSupportSdkVersion"]}",
            "constraint_layout"   : "com.android.support.constraint:constraint-layout:${versions["constraintLayoutVersion"]}",
            "runner"              : "com.android.support.test:runner:${versions["runnerVersion"]}",
            "espresso_core"       : "com.android.support.test.espresso:espresso-core:${versions["espressoVersion"]}",
            "junit"               : "junit:junit:${versions["junitVersion"]}",
            "support_annotations" : "com.android.support:support-annotations:${versions["annotationsVersion"]}",
            "design"              : "com.android.support:design:${versions["androidSupportSdkVersion"]}",
            "support-v4"          : "com.android.support:support-v4:${versions["androidSupportSdkVersion"]}",
            "cardview-v7"         : "com.android.support:cardview-v7:${versions["androidSupportSdkVersion"]}",
            "recyclerview-v7"     : "com.android.support:recyclerview-v7:${versions["androidSupportSdkVersion"]}",
            //方法数超过65535解决方法64K MultiDex分包方法
            "multidex"            : "com.android.support:multidex:${versions["multidexVersion"]}",

            //路由
            "arouter_api"         : "com.alibaba:arouter-api:${versions["arouterApiVersion"]}",
            "arouter_compiler"    : "com.alibaba:arouter-compiler:${versions["arouterCompilerVersion"]}",
            "arouter_annotation"  : "com.alibaba:arouter-annotation:${versions["arouterannotationVersion"]}",


            "butterknife_compiler": "com.jakewharton:butterknife-compiler:${versions["butterknifeVersion"]}",
            "butterknife"         : "com.jakewharton:butterknife:${versions["butterknifeVersion"]}",

            "gson"                : "com.google.code.gson:gson:${versions["gsonVersion"]}",
            "rxjava"              : "io.reactivex.rxjava2:rxjava:${versions["rxjavaVersion"]}",
            "rxandroid"           : "io.reactivex.rxjava2:rxandroid:${versions["rxandroidVersion"]}",
            "retrofit"            : "com.squareup.retrofit2:retrofit:${versions["retrofitVersion"]}",
            "convertergson"       : "com.squareup.retrofit2:converter-gson:${versions["convertergsonVersion"]}",
            "rxjava2adapter"      : "com.squareup.retrofit2:adapter-rxjava2:${versions["rxjava2adapterVersion"]}",
            "logginginterceptor"  : "com.squareup.okhttp3:logging-interceptor:${versions["logginginterceptorVersion"]}",

            "glide"               : "com.github.bumptech.glide:glide:${versions["glideVersion"]}",
            "baservadapte"        : "com.zhy:base-rvadapter:${versions["baservadapterVersion"]}",
            "flowlayout"          : "com.zhy:flowlayout-lib:${versions["flowlayoutVersion"]}",
            "permission"          : "com.yanzhenjie:permission:${versions["permissionVersion"]}",
    ]

}

然后一定要记得 在application 的 gadle中添加

apply from: "config.gradle"

否则会报 类似这种的错误

ERROR: Cannot get property 'versions' on extra properties extension as it does not exist

然后就是修改commonlibrary的gradle

apply plugin: 'com.android.library'

android {
    compileSdkVersion rootProject.ext.versions.compileSdkVersion
    buildToolsVersion rootProject.ext.versions.buildToolsVersion
    defaultConfig {
        minSdkVersion rootProject.ext.versions.minSdkVersion
        targetSdkVersion rootProject.ext.versions.targetSdkVersion
        versionCode rootProject.ext.versions.versionCode
        versionName rootProject.ext.versions.versionName

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        //Arouter路由配置
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
                includeCompileClasspath = true
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility = '1.8'
        targetCompatibility = '1.8'
    }
    compileOptions {
        targetCompatibility rootProject.ext.versions.javaSDKVersion
        sourceCompatibility rootProject.ext.versions.javaSDKVersion
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    //把implementation 用api代替,它是对外部公开的, 所有其他的module就不需要添加该依赖
    api rootProject.ext.dependencies["support_annotations"]
    api rootProject.ext.dependencies["junit"]

    //MultiDex分包方法
    api rootProject.ext.dependencies["multidex"]

    //Arouter路由
    annotationProcessor rootProject.ext.dependencies["arouter_compiler"]
    api rootProject.ext.dependencies["arouter_api"]
    api rootProject.ext.dependencies["arouter_annotation"]
    //解析
    api rootProject.ext.dependencies["gson"]
    //rxjava和网络
    api rootProject.ext.dependencies["rxjava"]
    api rootProject.ext.dependencies["rxandroid"]
    api rootProject.ext.dependencies["retrofit"]
    api rootProject.ext.dependencies["convertergson"]
    api rootProject.ext.dependencies["rxjava2adapter"]
    api rootProject.ext.dependencies["logginginterceptor"]
    //图片加载
    api rootProject.ext.dependencies["glide"]
    //黄油刀
    annotationProcessor rootProject.ext.dependencies["butterknife_compiler"]
    api rootProject.ext.dependencies["butterknife"]
    //权限
    api rootProject.ext.dependencies["permission"]
    api 'com.flyco.tablayout:FlycoTabLayout_Lib:2.1.2@aar'
    implementation project(path: ':uilibrary')

}

把原来自己原来封装的baseActivity 、网络等一些内容移动进来


image.png

这样我们对commonLib的封装就完成了

2.业务模块的封装

每个不同的app都有着自己不同封装,这个是需要根据具体的逻辑来的 就让我们先看一下原理的界面来抽出不同的业务模块。
先看具体界面


image.png

最终一共分为五个模块、
home:入口+首页模块
answer:答题测试模块
shop:积分商城模块
me:个人中心模块
commonActiivty:需要在四个模块中都需要用到的模块 如登录注册 等
业务模块遇到的问题

1.butterknife问题

application的gradle中添加 classpath 'com.jakewharton:butterknife-gradle-plugin:9.0.0'
需要在每个模块的gradle中添加

apply plugin: 'com.jakewharton.butterknife
dependencies {
    annotationProcessor rootProject.ext.dependencies["butterknife_compiler"]
}
2.Arouter配置问题

一定要早每一个module中都要配置

  javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
                includeCompileClasspath = true
            }
        }
3.application和library转换问题

在module的gradle中添加根据config中多的isModule判断是集成模式还是单个运行模式
if (Boolean.valueOf(rootProject.ext.isModule)) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}

4.资源文件问题

在给资源文件命名的时候一定要以当前的module为前缀

5.不同xml问题

根据模式判断加载那个xml
在module/AndroidManifest.xml'下面要记得配置入口啊
sourceSets {
main {
if (Boolean.valueOf(rootProject.ext.isModule)) {
manifest.srcFile 'src/main/module/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
//排除java/debug文件夹下的所有文件
exclude '*module'
}
}
}
最后上传组件化demo: https://github.com/525642022/ComponentApplication

上一篇 下一篇

猜你喜欢

热点阅读