随着app迭代,以及功能需求的更新,项目中的冗余代码量增多,代码各模块间的耦合增强,不利于更新以及测试,所以开始了组建化的设计。
android的组件化基于module的两种属性
application属性,module可以作为独立的app运行
apply plugin: ‘com.android.application’
library属性,module不可独立运行,作为依赖库文件
apply plugin: ‘com.android.library’
通过控制module的此属性可以间module在app以及依赖库之间进行切换,此属性在build.gradle文件中。
而且项目的gradle文件是可以公用的,所以可以新建一个config.gradle文件进行对module以及一些依赖进行配置。
/**
* 全局统一配置文件
*/
ext {
//true 每个业务Module可以单独开发
//false 每个业务Module以lib的方式运行
//修改之后需要Sync方可生效
isModule = false
//版本号
versions = [
applicationId : "com.example.bwq.moduletest", //应用ID
versionCode : 1, //版本号
versionName : "1.0.0", //版本名称
compileSdkVersion : 28,
buildToolsVersion : "27.0.3",
minSdkVersion : 16,
targetSdkVersion : 28,
androidSupportSdkVersion: "28.+",
constraintLayoutVersion : "1.1.3",
runnerVersion : "1.0.2",
espressoVersion : "3.0.2",
junitVersion : "4.12",
multidexVersion : "1.0.2",
butterknifeVersion : "8.8.1",
arouterApiVersion : "1.4.0",
arouterCompilerVersion : "1.2.1",
arouterannotationVersion: "1.0.4",
recyclerview : "28.+",
cardview : "28.+",
//三方依赖的版本控制
]
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"]}",
recyclerview : "com.android.support:recyclerview-v7:${versions["recyclerview"]}",
cardview : "com.android.support:cardview-v7:${versions["cardview"]}",
//三方依赖的库地址
]
}
其中isModule为控制module为组建模式还是app模式的开关
因此组建module的属性可通过开关来判断,在组建build.gradle文件开头设置为如下:
if (Boolean.valueOf(rootProject.ext.isModule)) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
在组建化中我将app分为三层,
第一层:app层
app入口,初始化页面,以及主页通过在主页viewpager中添加fragment使其成为正常app的主页。
第二层:组建层
将项目按功能划分为各个组建,如登录组建,首页组建,我的组建等,组建间通过路由的方式跳转以及传递数据。
第三层:基础层
项目基础层,公用控件,公用的方法资源文件,网络请求方法,以及依赖库的封装都在这层进行实现。
组建层以及app层的每一个module均依赖基础层,app层依赖每一个组建层以及基础层。
基础层中将在配置文件中的依赖方法,进行依赖,基础层不需要成为app独立运行,因此无需设置application以及library的开关,依赖关键字使用api:
apply plugin: 'com.android.library'
apply plugin: 'com.jakewharton.butterknife'
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"
//MultiDex分包方法
multiDexEnabled true
//Arouter路由配置
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
includeCompileClasspath = true
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
//把implementation 用api代替,它是对外部公开的, 所有其他的module就不需要添加该依赖
api rootProject.ext.dependencies["appcompat_v7"]
api rootProject.ext.dependencies["constraint_layout"]
api rootProject.ext.dependencies["cardview-v7"]
api rootProject.ext.dependencies["recyclerview-v7"]
api rootProject.ext.dependencies["support-v4"]
api rootProject.ext.dependencies["design"]
api rootProject.ext.dependencies["support_annotations"]
//MultiDex分包方法
api rootProject.ext.dependencies["multidex"]
//黄油刀
annotationProcessor rootProject.ext.dependencies["butterknife_compiler"]
api rootProject.ext.dependencies["butterknife"]
//Arouter路由
annotationProcessor rootProject.ext.dependencies["arouter_compiler"]
api rootProject.ext.dependencies["arouter_api"]
api rootProject.ext.dependencies["arouter_annotation"]
api rootProject.ext.dependencies["recyclerview"]
api rootProject.ext.dependencies["cardview"]
}
第二层中因每个组建均需要成为独立app进行测试以及开发,因此,他的manifest文件需要两套,一套为普通library的没有app入口,一套为application的有app入口的文件。
新建module,选择phone&table module,建立标准app module,main包下新建路径manifest放置module作为app时的manifest文件
project显示模式下main文件夹
黄色框为新建文件夹以及新建文件:
manifest配置为基础app配置
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bwq.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/MyAppTheme"
android:name=".debug.MainApplication">
<activity android:name=".debug.MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
红色框中的manifest文件为library时的
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.bwq.main">
<application>
<activity android:name=".debug.MainActivity"/>
</application>
</manifest>
在java中新建debug包,放置一些作为独立app时的配置,如继承自基础层的Application类,如果组建入口为fragment时展示fragment的activity,之后在当前module的builde.gradle中配置
if (Boolean.valueOf(rootProject.ext.isModule)) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
apply plugin: 'com.jakewharton.butterknife'
android {
compileSdkVersion rootProject.ext.versions.compileSdkVersion
buildToolsVersion rootProject.ext.versions.buildToolsVersion
defaultConfig {
if (Boolean.valueOf(rootProject.ext.isModule))
applicationId rootProject.ext.versions.applicationId
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"
//MultiDex分包方法
multiDexEnabled true
//Arouter路由配置
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
includeCompileClasspath = true
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
sourceSets {
//配置当前module作为app和作为library时的manifest文件以及作为library时所需要忽略的文件
main {
if (Boolean.valueOf(rootProject.ext.isModule)) {
manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
exclude '*debug/**'
exclude '*manifest/**'
}
}
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
//butterKnife
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
annotationProcessor rootProject.ext.dependencies["butterknife_compiler"]
annotationProcessor rootProject.ext.dependencies["arouter_compiler"]
api project(':basis_library')
}
为了方便组建间的跳转,在基础层中BaseApplication类中初始化路由,BaseApplication为所有组建以及app的Application类的基类。
/**
* 初始化ARouter
*/
public void initARouter() {
if (BuildConfig.DEBUG) {
ARouter.openLog();
ARouter.openDebug();
}
ARouter.init(instance);
}
增加组建化后的跳转工具类
public class ARouterUtils {
/**
* 根据path返回Fragment
*
* @param path path
* @return fragment
*/
public static BaseLazyFragment getLazyFragment(String path) {
return (BaseLazyFragment) ARouter.getInstance()
.build(path)
.navigation();
}
public static BaseFragment getFragment(String path) {
return (BaseFragment) ARouter.getInstance()
.build(path)
.navigation();
}
/**
* 根据path返回Activity
*
* @param path path
* @return Activity
*/
public static BaseActivity getActivity(String path) {
return (BaseActivity) ARouter.getInstance()
.build(path)
.navigation();
}
/**
* 根据path返回FragmentActivity
*
* @param path path
* @return FragmentActivity
*/
public static BaseFragmentActivity getFragmentActivity(String path) {
return (BaseFragmentActivity) ARouter.getInstance()
.build(path)
.navigation();
}
}
路由跳转URL地址
/**
* 功能模块入口
*/
public interface ARouterConfig {
/**
* 登录页面
*/
String LOGIN = "/login/LoginActivity";
/**
* main
*/
String MAIN = "/main/MainFragment";
/**
* mine
*/
String MINE = "/mine/MineFragment";
}
app层:
builde.gradle配置:
apply plugin: 'com.android.application'
apply plugin: 'com.jakewharton.butterknife'
android {
compileSdkVersion rootProject.ext.versions.compileSdkVersion
buildToolsVersion rootProject.ext.versions.buildToolsVersion
defaultConfig {
applicationId rootProject.ext.versions.applicationId
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"
//MultiDex分包方法
multiDexEnabled true
//Arouter路由配置
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
includeCompileClasspath = true
}
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
annotationProcessor rootProject.ext.dependencies["butterknife_compiler"]
annotationProcessor rootProject.ext.dependencies["arouter_compiler"]
api project(':basis_library')
if (!Boolean.valueOf(rootProject.ext.isModule)) {
api project(':main')
api project(':login')
api project(':mine')
}
}
至此,组建化方案完成。
最后说一些注意的问题,各层的依赖关键字需要使用api,不同组建间的资源文件由于在组合后可能会有冲突,各组建间的资源文件建议以组建名开头,如login_back
网友评论