转载请标明出处:【顾林海的博客】
前言
在以前的项目中都是建一个基础库,项目依赖基础库,主项目中集成了所有的功能,这样的化导致主项目的臃肿,并且功能难以拆分,如果是有规模的公司,一般有好几个业务部门,业务部门之间的交流成本高,2015年所在的同程旅游亦是如此,所有项目组的代码都是在同一个项目中,虽然做了包的划分,但还是难以维护,业务的不断增加,代码的数量也会越来越多,单一工程下的架构势必会阻碍开发进度。为此提出组件化开发,组件化开发将业务拆分成一个个组件,每一个组件可以单独编译,并且可以相互依赖,通过路由协议,达到Activity之间的解耦,为此,可以将项目进行分层,基础组件包含(三方SDK、网络请求操作、图片加载操作、公共工具类、日志分析、公共View),其次是业务组件依赖与基础组件,如果有必要可以在业务组件与基础组件之间增加一层公共业务组件用于公共业务的操作(比如账户相关的操作)。划分后的分层图如下:
组件化开发
下面会同一个项目的框架讲解组件化开发的具体流程,讲解过程中并没有把公共业务组件添加进去,如果大家有这层需求可以自行添加。
这里需要了解一些概念:
application属性,可以独立运行的Android程序,也就是我们的APP;
apply plugin: ‘com.android.application’
2、library属性,不可以独立运行,一般是Android程序依赖的库文件;
apply plugin: ‘com.android.library’
项目的目录结构如下:
在项目中app是我们的主项目,一般包含引导页和主界面,可以称它为壳,baselibrary是我们的基础库,module下是我们的业务组件,这里的两个业务组件分别是咨询组件和订单组件,我们的业务组件和壳都会依赖基础库。
在业务组件下,比如订单组件下我又创建了两个module,分别是用于编译成APK的工程和作为library的工程。
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
minSdkVersion 17
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.alibaba:arouter-api:1.2.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.1.2'
compile project(':module:order:orderlibrary')
compile project(':baselibrary')
}
这是ordermanager的工程gradle,可以看出它依赖于基础库和具体的订单组件,可以把ordermanager看做是订单组件的入口,并直接进行编译生成APK,consultingmanager也是如此。
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
minSdkVersion 17
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.alibaba:arouter-api:1.2.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.1.2'
testCompile 'junit:junit:4.12'
compile project(':baselibrary')
}
这是orderlibrary的gradle,orderlibrary依赖与基础库,并且它才是真正订单的组件,内部是一系列订单实现的功能。
单独编译ordermanager,并通过路由协议进行跳转,这里使用的是阿里的ARouter,查看ordermanager的入口代码:
package com.glh.ordermanager;
import android.view.View;
import android.widget.Button;
import com.alibaba.android.arouter.launcher.ARouter;
import com.glh.baselibrary.BaseActivity;
/**
* 订单模块
* Created by glh on 2017-09-12.
*/
public class MainActivity extends BaseActivity {
private Button mOrderButton;
@Override
protected int layout() {
return R.layout.order_layout;
}
@Override
protected void initView() {
mOrderButton = findViewById(R.id.btn_order);
mOrderButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
orderModule();
}
});
}
public void orderModule() {
ARouter.getInstance().build("/orderlibrary/order/main").navigation();
}
}
编译并运行:
同理,app主项目依赖与基础库,并根据需求依赖相应的业务组件。
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "com.glh.tcproject"
minSdkVersion 17
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile 'com.alibaba:arouter-api:1.2.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.1.2'
compile project(':module:order:orderlibrary')
compile project(':module:consulting:consultinglibrary')
compile project(':baselibrary')
}
package com.glh.tcproject;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.alibaba.android.arouter.launcher.ARouter;
import com.glh.baselibrary.BaseActivity;
import com.glh.consultinglibrary.ConsultingManActivity;
import com.glh.orderlibrary.OrderMainActivity;
public class MainActivity extends BaseActivity {
private Button mOrderButton;
private Button mConsultingButton;
@Override
protected int layout() {
return R.layout.activity_main;
}
@Override
protected void initView() {
mOrderButton = findViewById(R.id.id_main_order);
mConsultingButton = findViewById(R.id.id_main_consulting);
mOrderButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance().build("/orderlibrary/order/main").navigation();
}
});
mConsultingButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance().build("/consultinglibrary/consulting/main").navigation();
}
});
}
}
编译app主项目,并运行:
除了以上操作,不同业务组件也是可以相互依赖,比如想在订单组件中使用咨询组件,可以在orderlibrary中引入consultinglibrary:
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile 'com.alibaba:arouter-api:1.2.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.1.2'
testCompile 'junit:junit:4.12'
compile project(':baselibrary')
compile project(':module:consulting:consultinglibrary')
}
package com.glh.orderlibrary;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import com.glh.baselibrary.BaseActivity;
/**
* 订单模块
* Created by glh on 2017-09-12.
*/
@Route(path = "/orderlibrary/order/main")
public class OrderMainActivity extends BaseActivity {
private Button mOrderButton;
private Button mConsultingButton;
@Override
protected int layout() {
return R.layout.module_order_layout;
}
@Override
protected void initView() {
mOrderButton = findViewById(R.id.id_order);
mConsultingButton = findViewById(R.id.id_consulting);
mOrderButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
orderModule();
}
});
mConsultingButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance().build("/consultinglibrary/consulting/main").navigation();
}
});
}
public void orderModule() {
Toast.makeText(this, "订单项目", Toast.LENGTH_SHORT).show();
}
}
重新编译ordermanager,并运行:
组件化开发已经讲解完,关于组件化开发网上有很多文章,这里只是给出了组件化开发的思路,最后有关组件化开发导致的资源冲突,我的解决方案是规范,是的,可以规定每个业务组件的资源文件已组件名开头,这样的话就不会造成资源冲突。
项目的github地址在这里,大家可以下载下来看看,如果对你有一丁点帮助,那么写这篇文章也是值得的。