組件化項目,經過gradle腳本,實現module在編譯期隔離,運行期按需加載,實現組件間解耦,高效單獨調試。php
https://github.com/wang709693972wei/CompontentDemo
先來一張效果圖,建議讀者clone項目後跟着項目看這篇文章,有任何不明白的地方可留言或者聯繫我,我看到後會馬上回復你。java
組件化就是將一個app分紅多個Module,以下圖,每一個Module都是一個組件(也能夠是一個基礎庫供組件依賴),開發的過程當中咱們能夠單獨調試部分組件,組件間不須要互相依賴,但能夠相互調用,最終發佈的時候全部組件以lib的形式被主app工程依賴並打包成一個apk。android
一、全局設置Gradle ,每個業務Module須要的版本都定義在這裏方便後期維護多個Module版本號git
ext {
// Sdk and tools minSdkVersion = 16 targetSdkVersion = 26 compileSdkVersion = 26 buildToolsVersion = '26.0.2' supportLibraryVersion = '26.1.0' // App dependencies aRouter = '1.2.2' leakcanaryVersion = '1.3' glideVersion = '3.7.0' } ####每一個業務Module編譯依賴版本 compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
二、模式切換github
組件化後的每個業務的module均可以是一個單獨的APP(isModuleRun=false), release 包的時候各個業務module做爲lib依賴,這裏徹底由一個變量控制,在根項目 gradle.properties裏面的 isModuleRun=true。api
isModuleRun狀態不一樣,加載application和AndroidManifest都不同,以此來區分是獨立的APK仍是lib,
實現方式以下
在build.grade
裏面配置安全
if (isModuleRun.toBoolean()) { apply plugin: 'com.android.application' } else { apply plugin: 'com.android.library' } ### 單Module運行須要配置 sourceSets { main { if (isModuleRun.toBoolean()) { manifest.srcFile 'src/main/debug/AndroidManifest.xml' } else { manifest.srcFile 'src/main/AndroidManifest.xml' java { //所有Module一塊兒編譯的時候剔除debug目錄 exclude '**/debug/**' } } } }
三、資源衝突bash
業務Module和BaseModule資源文件名稱重複會產生衝突,解決方案在
每一個 module 都有 app_name,爲了避免讓資源名重名,在每一個組件的 build.gradle 中增長 resourcePrefix 「xxx_強行檢查資源名稱前綴。
固定每一個組件的資源前綴。可是 resourcePrefix 這個值只能限定 xml 裏面的資源,並不能限定圖片資源。
我的認爲約定大於配置,團隊內協定好規範,能夠避免衝突。微信
四、組件通信
不熟悉ARouter基本用法的能夠看看個人這篇文章
阿里巴巴ARouter基本使用方法app
組件通信框架在github上有star最多的有ARouter和ActivityArouter,前者是我的項目,後者是阿里巴巴開源,權衡之下選擇阿里的ARouter,
各業務Module以前不須要任何依賴能夠經過路由跳轉,完美解決業務之間耦合
使用方式以下。
if (BuildConfig.DEBUG) { // 這兩行必須寫在init以前,不然這些配置在init過程當中將無效 ARouter.openLog(); // 打印日誌 ARouter.openDebug(); // 開啓調試模式(若是在InstantRun模式下運行,必須開啓調試模式!線上版本須要關閉,不然有安全風險) } ARouter.init(this); // 儘量早,推薦在Application中初始化
compile "com.alibaba:arouter-api:$rootProject.aRouter" 每一個業務Module都須要添加註解 annotationProcessor 'com.alibaba:arouter-compiler:1.1.3'
跳轉方法
在目標Activity上添加path
@Route(path = ARouterManager.BModuleActivity)
public class BModuleActivity extends BaseActivity { @Autowired public String name; @Autowired(name = "age") int age; TextView txt; @Override protected int getLayoutId() { return R.layout.b_module_layout; } @Override protected void initView() { txt = findViewById(R.id.txt); //String name = getIntent().getStringExtra("name"); 也能夠這樣接受參數 ARouter.getInstance().inject(this); txt.setText("name:" + name + ",age:" + age); #開始跳轉 btn2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 2\. 跳轉並攜帶參數 ARouter.getInstance().build(ARouterManager.BModuleActivity) .withString("name", "888") .withInt("age", 11) .navigation(); } });
/** * 路由管理類 */ public final class ARouterManager { public static final String AFragment = "/amodule/AFragment"; public static final String BFragment = "/bmodule/BFragment"; public static final String CFragment = "/cmodule/CFragment"; public static final String AModuleActivity = "/amodule/AAModuleActivity"; public static final String BModuleActivity = "/bmodule/BModuleActivity"; public static final String CModuleActivity = "/cmodule/CModuleActivity"; }
上述只使用了ARouter的簡單用法,更多進階用法請參考ARouter文檔,
ARouter
五、Application
當組件單獨運行的時候,每一個Module自成一個APK,那麼就意味着會有多個Application,很顯然咱們不肯意重複寫這麼多代碼,因此咱們只須要定義一個BaseApplication便可,其它的Application直接繼承此BaseApplication就OK了,BaseApplication裏面還可定義公用的參數。
連接:https://www.jianshu.com/p/010d946e8f67,轉載請註明原創
微信公衆號:終端研發部