無論全世界全部人怎麼說,我都認爲本身的感覺纔是正確的。不管別人怎麼看,我毫不打亂本身的節奏。喜歡的事天然能夠堅持,不喜歡的怎麼也長久不了。java
—— 村上春樹android
隨着App的不斷迭代,業務會變得愈來愈複雜,業務模塊會愈來愈多,且每一個模塊的代碼也會變得愈來愈多。爲了應對這一場景,咱們須要把不一樣的業務模塊劃分紅一個個組件,在修改業務代碼的時候只須要在對應模塊修改就能夠了。經過高內聚,低耦合的業務模塊來保證工程的健壯性和穩定性。如今問題來了,當組件的數量變得越來多的時候,咱們如何管理業務組件呢?git
原創聲明: 該文章爲原創文章,未經博主贊成嚴禁轉載。 以前的文章是分享本人博客的,如今在專欄從新發一次。github
先來看看Android組件化須要實現的目標。(什麼是組件化構建?)數據庫
對於第一點:須要根據技術架構和業務架構來劃分模塊,這裏須要根據實際狀況來考慮。咱們須要優化的是第2、3、四點。bash
對於第二點:Android是經過應用com.android.application或com.android.library來決定該模塊是以App模式仍是以Library模式構建。App模式和Library模式的最大區別就是,App可以啓動,而Library不能夠。因此若是咱們的模塊能獨立啓動的話,咱們須要每次手動去改動模塊的build.gradle文件。好一點的作法定義一個布爾值來判斷是否處於debug模式,可是這裏有個問題是,不是每一個模塊都能獨立啓動的。因此不管採用何種方案,都須要咱們手動管理。架構
對於第三點:當咱們開發好業務模塊後,可能咱們須要頻繁的新增或刪除某些業務模塊。若是是這樣的話,咱們也是須要頻繁手動修改App的build.gradle。app
對於第四點:有時候,咱們可能會在不一樣的App中引用相同的組件(例如:滴滴的普通版和企業版,普通版包含企業版的功能),這個時候,咱們也不但願要頻繁手動管理組件依賴,特別是在組件還能夠獨立運行的時候。框架
因此,在咱們實踐組件化的時候,最大的問題就是,咱們須要頻繁的手動build.gradle文件來管理組件應用的插件和App的依賴。maven
先安利下筆者寫的Gradle插件:Calces。若是以爲這個插件有用的話,能夠star下,若是你有更好的想法的話,能夠向我提交pull request。
廢話少說,一下是經過Calces快速實現Android組件化構建的流程。
Demo地址:SimpleCalces
項目結構:
引入依賴庫 在Gradle 2.1及更高版本的插件構建腳本代碼: 在項目的build.gradle中
buildscript {
...
}
plugins {
id "calces.modules" version "1.0.11"
}
複製代碼
在較舊版本的Gradle中或須要動態配置的狀況下的插件構建腳本代碼:
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "gradle.plugin.com.tangpj.tools:calces:1.0.11"
}
}
apply plugin: "calces.appConfig"
複製代碼
在項目build.gradle配置AppConfig
appConfig {
debugEnable false
apps {
app{
modules ':library1', ':library2'
}
}
modules{
library1{
mainActivity ".Library1Activity"
applicationId "com.tangpj.library1"
isRunAlone true
}
library2{
mainActivity ".Library2Activity"
applicationId "com.tangpj.library2"
isRunAlone true
}
}
}
複製代碼
在modules(子模塊)引入模塊自動化構建插件 (注意:不須要手動配置com.android.library或com.android.application)
apply plugin: 'calces.modules'
複製代碼
這樣咱們就完成了組件化的構建了,是的,咱們再也不須要再手動管理單個組件了與App的構建了,經過Calces,咱們能實現快速的組件化構建與多App同時構建。
那麼問題來了,咱們如何實現組件間的通訊呢?在簡單的項目中,推薦該Demo同樣,經過使用Android隱式Intent來實現組件間通訊。在中大型項目中,筆者推薦使用阿里的路由解決方案:ARouter。具體使用方法參考官方文檔就能夠了,使用方法十分簡單。
**注意:**在使用隱式Intent實現組件件通訊的時候須要注意找不到相應組件異常:java.lang.IllegalStateException: Could not execute method of the activity。致使這個異常的緣由是找不到目標組件致使的,因此在實際開發的時候,須要捕獲這一異常,而且根據項目實際狀況來進行實際的處理。使用ARouter框架則能經過設置降級策略來實現異常處理(查看ARouter文檔瞭解更多)。
若是隻是實現項目的簡單組件化,那麼看到這裏就能夠了,若是但願實現更加靈活的組件化架構的讀者能夠繼續看下去,下面筆者將全面分析組件化的優點與筆者總結的組件化構建思想。
組件化構建與其說是一種技術,不如說是一種思想。組件化構建是經過對項目從新劃分紅一個個高內聚、低耦合的模塊來解決項目過於臃腫,代碼過於複雜的一種架構思想。
咱們經過對Google官方的架構演示Demo todo-mvp進行拆分來對Android組件化進行深刻的分析。
Demo地址:TodoCalces
todo系列app是Google android-architecture項目中爲了演示Android架構的最佳實現而編寫的一系列演示Demo。todo app的特色是,它足夠簡單,代碼量少,易於理解。可是又不會過於簡單,由於它是一個包含完成功能的App。它實現了任務列表、任務詳情、新建任務、編輯任務、統計任務的功能。
todo-mvp實現的功能:
咱們將以todo-mvp的功能來劃分爲4個業務模塊,將底層劃分爲2個模塊,分別是superLib(提供mvp架構支持與其它的一些支持庫功能)與dataLib(數據支持模塊,Room提供底層數據庫支持功能)。對於大型項目還能夠加入resLib支持模塊,用來存放公共圖片資源、字符穿資源、樣式等。
架構劃分圖以下:
從架構圖能夠看出,全部的業務組件都依賴底層庫,而APP又依賴於業務組件,APP組件在這裏是做爲一個獨立組件存在的。在通常的組件化實踐中,都不包含APP這個組件的,APP組件的存在是有其意義的。
首先,咱們的組件化除了實現組件的獨立管理和動態配置APP所依賴的組件外,還有一個十分重要的目的就是,經過組合不一樣的組件,打包多個不一樣的APP。例如,QQ有分普通版和輕聊版,輕聊版是功能簡化版的QQ。若是咱們使用組件化來管理工程的話,咱們只須要把不須要的模塊移除掉就能夠了。而APP組件在這裏的做用是充當一個包裝盒,把須要的組件包裝進來。而且咱們能夠經過控制包裝盒的樣式來配置不一樣的APP風格。在這裏咱們能夠經過Application中的Style來實現。
這裏咱們仍是以todo-mvp爲例,例如咱們須要實現一個不包含統計功能的todo APP,按照咱們的原理,咱們只須要去掉statistics的依賴就能夠了。
架構劃分圖以下:
若是nostatsitcs須要不一樣的配色的方案的話,只須要在AndroidManifest的application標籤中配置對應的theme就能夠了。
經過上面的分析,咱們來試下對todo-mvp項目按照業務功能來劃分組件。咱們先來看看劃分後的目錄:
好了,咱們已經對todo-mvp項目進行初步的劃分了。根據上面分析的理論得知,咱們的業務模塊是能夠單獨運行的,而且咱們可以快速構建一個不包含statistics模塊的APP。
咱們只須要使用Calces就能快速實現咱們須要的功能。
按照Calces的教程,咱們得知,實現Calces只須要三個步驟:
第一點和第三點在其它全部項目中的配置都是同樣的,在這裏不做論述,下面咱們看看對於TodoCalces項目,咱們要如何配置AppConfig 。
appConfig {
debugEnable false
apps {
app {
mainActivity "com.tangpj.tasks.TasksActivity"
modules ':modules:addtask',
':modules:taskdetail',
':modules:tasks',
':modules:statistics'
}
app2 {
name 'nostatistic'
applicationId 'com.tangpj.nostatistic'
modules ':modules:addtask',
':modules:taskdetail',
':modules:tasks'
}
}
modules {
addtask {
name ":modules:addtask"
applicationId "com.tangpj.addtask"
mainActivity ".AddEditTaskActivity"
isRunAlone false
}
taskdetail {
name ":modules:taskdetail"
applicationId "com.tangpj.taskdetail"
mainActivity ".TaskDetailActivity"
isRunAlone true
}
task {
name ":modules:tasks"
applicationId "com.tangpj.tasks"
mainActivity ".TasksActivity"
isRunAlone true
}
statistics {
name ":modules:statistics"
applicationId "com.tangpj.statistics"
mainActivity ".StatisticsActivity"
isRunAlone true
}
}
}
複製代碼
根據AppConfig能夠得出,咱們分別配置了2個APP,分別是app1和app2。而且app2中是沒有依賴statistics的。如今咱們兩個APP運行的對比圖。
app1(帶statistics模塊):
app2(不帶statistics模塊):
從運行圖能夠看出,app1和app2的配色方案是不同的,而且app2中不帶statistics模塊,經過對項目實行合理的劃分和引入Calces就可以快速實現組件化構建了。
**結論:**經過Calces能輕鬆實現業務組件的管理,多APP的快速構建。當咱們的業務組件只有4個的時候,可能沒法體現Calces的優點,可是若是咱們的業務組件有40個的時候,Calces給咱們帶來的優點就很是明顯了。咱們能夠經過靈活依賴不一樣的組件,實現快速構建多個APP的目的。就像Calces的介紹圖案同樣,把組件當成積木來使用。
Android自動化測試展開來講是一個很是大而且不算簡單的工程,在這裏筆者不打算展開來講。只是簡單的介紹組件化構建如何讓咱們更方便地去測試。
並非全部的自動化測試都同樣,它們一般在使用範圍、實現難度和執行時間上存在不一樣。咱們通常把自動化測試劃分爲三種分別是:
爲了優化投資回報率,代碼庫應該包含大量的單元測試、少許集成測試以及更少的功能測試。
佔好比下圖所示:
從上文知道,在咱們的組件化分的時候,會劃分一個基礎依賴庫(superLib)。基礎依賴庫爲咱們的項目提供了基本的支持,而且該庫在項目中是比較穩定、而且不包含業務邏輯的,因此在基礎依賴庫中,咱們應該大量應用單元測試。而集成測試則適用於咱們的數據依賴庫(dataLib)中,咱們能夠經過集成測試來驗證產品代碼與數據模塊的交互。而咱們的業務模塊中包含了大量的業務邏輯,這部分是常常變更的部分,咱們能夠爲咱們的業務模塊編寫一些UI自動化測試代碼,可是由於業務(界面)常常變更的緣由,因此這部分測試代碼是難以維護,而且複用性十分低的。。
最後,咱們得出的結論是:應該把主要精力放在單元測試上,因此若是當你的精力不足以編寫全部測試代碼的時候,你應該把主要的精力放在單元測試上,而不是放在收益最小的功能測試上。
關於自動化測試,筆者給的建議就到這裏了,若是須要深刻理解測試的話,能夠自行查找資料,或者關注筆者的博客。後續的博客中,有可能會寫關於自動化測試相關的知識。
經過Calces插件,咱們在實現Android組件化時只須要關注如何合理劃分組件的架構與如何實現組件間的通訊就能夠了。對於Android組件化來講,最主要問題有兩個:
第二個問題,能夠經過Calces快速解決,至於第一個問題,筆者給出的指導就是,業務模塊在合理的狀況下要儘量的小,由於越小的模塊,越容易達到高內聚低耦合的目的。讀者不須要擔憂項目模塊劃分得過於細不便於管理的問題,由於Calces可以輕鬆幫你管理好各個模塊。
Android開發利器之Data Binding Compiler V2 —— 搭建Android MVVM徹底體的基礎
若是這片文章對你有所啓發的話,能夠關注下筆者的公衆號或GitHub。
掃一掃關注我: