摘要:我們一般把自動化測試劃分為三種分別是單元測試目的是測試代碼的最小單元。集成測試用來測試一個完成的組件或子系統(tǒng),確保多個類之間的交互是否按預(yù)期運(yùn)行。集成測試需要比單元測試需要更長的執(zhí)行時間,而且更加難以維護(hù),失敗的原因難以診斷。
前言;為什么我們要用Gradle管理組件呢?先來看看Android組件化需要實(shí)現(xiàn)的目標(biāo)
按照業(yè)務(wù)邏輯劃分模塊
項(xiàng)目模塊能夠多帶帶啟動測試
能夠根據(jù)需求引入或刪除某些業(yè)務(wù)模塊
通過不同模塊的組合,組成不同的App
對于第一點(diǎn):需要根據(jù)技術(shù)架構(gòu)和業(yè)務(wù)架構(gòu)來劃分模塊,這里需要根據(jù)實(shí)際情況來考慮。我們需要優(yōu)化的是第二、三、四點(diǎn)。
對于第二點(diǎn):Android是通過應(yīng)用com.android.application或com.android.library來決定該模塊是以App模式還是以Library模式構(gòu)建。App模式和Library模式的最大區(qū)別就是,App能夠啟動,而Library不可以。所以如果我們的模塊能獨(dú)立啟動的話,我們需要每次手動去改動模塊的build.gradle文件。好一點(diǎn)的做法定義一個布爾值來判斷是否處于debug模式,但是這里有個問題是,不是每個模塊都能獨(dú)立啟動的。所以無論采用何種方案,都需要我們手動管理。
對于第三點(diǎn):當(dāng)我們開發(fā)好業(yè)務(wù)模塊后,可能我們需要頻繁的新增或刪除某些業(yè)務(wù)模塊。如果是這樣的話,我們也是需要頻繁手動修改App的build.gradle。
對于第四點(diǎn):有時候,我們可能會在不同的App中引用相同的組件(例如:滴滴的普通版和企業(yè)版,普通版包含企業(yè)版的功能),這個時候,我們也不希望要頻繁手動管理組件依賴,特別是在組件還可以獨(dú)立運(yùn)行的時候。
所以,在我們實(shí)踐組件化的時候,最大的問題就是,我們需要頻繁的手動build.gradle文件來管理組件應(yīng)用的插件和App的依賴。
一.使用Gradle來管理組件先安利下筆者寫的Gradle插件:Calces。如果覺得這個插件有用的話,可以star下,如果你有更好的想法的話,可以向我提交pull request。
廢話少說,一下是通過Calces快速實(shí)現(xiàn)Android組件化構(gòu)建的流程。
Demo地址:SimpleCalces
項(xiàng)目結(jié)構(gòu):
1.引入依賴庫
在Gradle 2.1及更高版本的插件構(gòu)建腳本代碼:
在項(xiàng)目的build.gradle中
buildscript {
...
}
plugins {
id "calces.modules" version "1.0.11"
}
在較舊版本的Gradle中或需要動態(tài)配置的情況下的插件構(gòu)建腳本代碼:
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "gradle.plugin.com.tangpj.tools:calces:1.0.11"
}
}
apply plugin: "calces.appConfig"
2.在項(xiàng)目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
}
}
}
3.在modules(子模塊)引入模塊自動化構(gòu)建插件 (注意:不需要手動配置com.android.library或com.android.application)
apply plugin: calces.modules
這樣我們就完成了組件化的構(gòu)建了,是的,我們不再需要再手動管理單個組件了與App的構(gòu)建了,通過Calces,我們能實(shí)現(xiàn)快速的組件化構(gòu)建與多App同時構(gòu)建。
那么問題來了,我們?nèi)绾螌?shí)現(xiàn)組件間的通信呢?在簡單的項(xiàng)目中,推薦該Demo一樣,通過使用Android隱式Intent來實(shí)現(xiàn)組件間通信。在中大型項(xiàng)目中,筆者推薦使用阿里的路由解決方案:ARouter。具體使用方法參考官方文檔就可以了,使用方法十分簡單。
注意:在使用隱式Intent實(shí)現(xiàn)組件件通信的時候需要注意找不到相應(yīng)組件異常:java.lang.IllegalStateException: Could not execute method of the activity。導(dǎo)致這個異常的原因是找不到目標(biāo)組件導(dǎo)致的,所以在實(shí)際開發(fā)的時候,需要捕獲這一異常,并且根據(jù)項(xiàng)目實(shí)際情況來進(jìn)行實(shí)際的處理。使用ARouter框架則能通過設(shè)置降級策略來實(shí)現(xiàn)異常處理(查看ARouter文檔了解更多)。
如果只是實(shí)現(xiàn)項(xiàng)目的簡單組件化,那么看到這里就可以了,如果希望實(shí)現(xiàn)更加靈活的組件化架構(gòu)的讀者可以繼續(xù)看下去,下面筆者將全面分析組件化的優(yōu)勢與筆者總結(jié)的組件化構(gòu)建思想。
二.組件化構(gòu)建簡述組件化構(gòu)建與其說是一種技術(shù),不如說是一種思想。組件化構(gòu)建是通過對項(xiàng)目重新劃分成一個個高內(nèi)聚、低耦合的模塊來解決項(xiàng)目過于臃腫,代碼過于復(fù)雜的一種架構(gòu)思想。
我們通過對Google官方的架構(gòu)演示Demo todo-mvp進(jìn)行拆分來對Android組件化進(jìn)行深入的分析。
Demo地址:TodoCalces
todo系列app是Google android-architecture項(xiàng)目中為了演示Android架構(gòu)的最佳實(shí)現(xiàn)而編寫的一系列演示Demo。todo app的特點(diǎn)是,它足夠簡單,代碼量少,易于理解。但是又不會過于簡單,因?yàn)樗且粋€包含完成功能的App。它實(shí)現(xiàn)了任務(wù)列表、任務(wù)詳情、新建任務(wù)、編輯任務(wù)、統(tǒng)計任務(wù)的功能。
todo-mvp實(shí)現(xiàn)的功能:
任務(wù)列表
任務(wù)詳情
新增/編輯任務(wù)
統(tǒng)計任務(wù)
我們將以todo-mvp的功能來劃分為4個業(yè)務(wù)模塊,將底層劃分為2個模塊,分別是superLib(提供mvp架構(gòu)支持與其它的一些支持庫功能)與dataLib(數(shù)據(jù)支持模塊,Room提供底層數(shù)據(jù)庫支持功能)。對于大型項(xiàng)目還可以加入resLib支持模塊,用來存放公共圖片資源、字符穿資源、樣式等。
架構(gòu)劃分圖如下:
從架構(gòu)圖可以看出,所有的業(yè)務(wù)組件都依賴底層庫,而APP又依賴于業(yè)務(wù)組件,APP組件在這里是作為一個獨(dú)立組件存在的。在一般的組件化實(shí)踐中,都不包含APP這個組件的,APP組件的存在是有其意義的。
首先,我們的組件化除了實(shí)現(xiàn)組件的獨(dú)立管理和動態(tài)配置APP所依賴的組件外,還有一個十分重要的目的就是,通過組合不同的組件,打包多個不同的APP。例如,QQ有分普通版和輕聊版,輕聊版是功能簡化版的QQ。如果我們使用組件化來管理工程的話,我們只需要把不需要的模塊移除掉就可以了。而APP組件在這里的作用是充當(dāng)一個包裝盒,把需要的組件包裝進(jìn)來。并且我們可以通過控制包裝盒的樣式來配置不同的APP風(fēng)格。在這里我們可以通過Application中的Style來實(shí)現(xiàn)。
這里我們還是以todo-mvp為例,例如我們需要實(shí)現(xiàn)一個不包含統(tǒng)計功能的todo APP,按照我們的原理,我們只需要去掉statistics的依賴就可以了。
架構(gòu)劃分圖如下:
如果nostatsitcs需要不同的配色的方案的話,只需要在AndroidManifest的application標(biāo)簽中配置對應(yīng)的theme就可以了。
使用Calces實(shí)現(xiàn)todo-mvp的組件化通過上面的分析,我們來試下對todo-mvp項(xiàng)目按照業(yè)務(wù)功能來劃分組件。我們先來看看劃分后的目錄:
好了,我們已經(jīng)對todo-mvp項(xiàng)目進(jìn)行初步的劃分了。根據(jù)上面分析的理論得知,我們的業(yè)務(wù)模塊是可以多帶帶運(yùn)行的,并且我們能夠快速構(gòu)建一個不包含statistics模塊的APP。
我們只需要使用Calces就能快速實(shí)現(xiàn)我們需要的功能。
按照Calces的教程,我們得知,實(shí)現(xiàn)Calces只需要三個步驟:
引入依賴庫
在項(xiàng)目的build.gradle中配置AppConfig
在業(yè)務(wù)模塊中引入模塊自動化構(gòu)c持續(xù)
第一點(diǎn)和第三點(diǎn)在其它所有項(xiàng)目中的配置都是一樣的,在這里不作論述,下面我們看看對于TodoCalces項(xiàng)目,我們要如何配置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
}
}
}
根據(jù)AppConfig可以得出,我們分別配置了2個APP,分別是app1和app2。并且app2中是沒有依賴statistics的?,F(xiàn)在我們兩個APP運(yùn)行的對比圖。
app1(帶statistics模塊):
app2(不帶statistics模塊):
從運(yùn)行圖可以看出,app1和app2的配色方案是不一樣的,并且app2中不帶statistics模塊,通過對項(xiàng)目實(shí)行合理的劃分和引入Calces就能夠快速實(shí)現(xiàn)組件化構(gòu)建了。
結(jié)論:通過Calces能輕松實(shí)現(xiàn)業(yè)務(wù)組件的管理,多APP的快速構(gòu)建。當(dāng)我們的業(yè)務(wù)組件只有4個的時候,可能無法體現(xiàn)Calces的優(yōu)勢,但是如果我們的業(yè)務(wù)組件有40個的時候,Calces給我們帶來的優(yōu)勢就非常明顯了。我們可以通過靈活依賴不同的組件,實(shí)現(xiàn)快速構(gòu)建多個APP的目的。就像Calces的介紹圖案一樣,把組件當(dāng)成積木來使用。
三.如何測試Android自動化測試展開來說是一個非常大并且不算簡單的工程,在這里筆者不打算展開來說。只是簡單的介紹組件化構(gòu)建如何讓我們更方便地去測試。
并不是所有的自動化測試都一樣,它們通常在使用范圍、實(shí)現(xiàn)難度和執(zhí)行時間上存在不同。我們一般把自動化測試劃分為三種分別是:
單元測試:目的是測試代碼的最小單元。在基于Java的項(xiàng)目中,這個單元是一個方法。單元測試容易編寫,快速執(zhí)行,并在開發(fā)過程中針對代碼的正確性提供寶貴的反饋。
集成測試:用來測試一個完成的組件或子系統(tǒng),確保多個類之間的交互是否按預(yù)期運(yùn)行。集成測試需要比單元測試需要更長的執(zhí)行時間,而且更加難以維護(hù),失敗的原因難以診斷。
功能測試:通常用于測試應(yīng)用程序端到端的功能,包括從用戶的角度與所有外部系統(tǒng)的交互。當(dāng)我們討論用戶角度時,通常是指用戶界面。因?yàn)橛脩艚缑鏁S著時間的推移發(fā)生變動,維護(hù)功能測試代碼會變得乏味而耗時。
為了優(yōu)化投資回報率,代碼庫應(yīng)該包含大量的單元測試、少量集成測試以及更少的功能測試。
占比如下圖所示:
從上文知道,在我們的組件化分的時候,會劃分一個基礎(chǔ)依賴庫(superLib)?;A(chǔ)依賴庫為我們的項(xiàng)目提供了基本的支持,并且該庫在項(xiàng)目中是比較穩(wěn)定、并且不包含業(yè)務(wù)邏輯的,所以在基礎(chǔ)依賴庫中,我們應(yīng)該大量應(yīng)用單元測試。
而集成測試則適用于我們的數(shù)據(jù)依賴庫(dataLib)中,我們可以通過集成測試來驗(yàn)證產(chǎn)品代碼與數(shù)據(jù)模塊的交互。而我們的業(yè)務(wù)模塊中包含了大量的業(yè)務(wù)邏輯,這部分是經(jīng)常變動的部分,我們可以為我們的業(yè)務(wù)模塊編寫一些UI自動化測試代碼,但是因?yàn)闃I(yè)務(wù)(界面)經(jīng)常變動的原因,所以這部分測試代碼是難以維護(hù),并且復(fù)用性十分低的。。
最后,我們得出的結(jié)論是:應(yīng)該把主要精力放在單元測試上,所以如果當(dāng)你的精力不足以編寫所有測試代碼的時候,你應(yīng)該把主要的精力放在單元測試上,而不是放在收益最小的功能測試上。
關(guān)于自動化測試,筆者給的建議就到這里了,如果需要深入理解測試的話,可以自行查找資料,或者關(guān)注筆者。后續(xù)的文章中,有可能會寫關(guān)于自動化測試相關(guān)的知識。
小結(jié)通過Calces插件,我們在實(shí)現(xiàn)Android組件化時只需要關(guān)注如何合理劃分組件的架構(gòu)與如何實(shí)現(xiàn)組件間的通信就可以了。對于Android組件化來說,最主要問題有兩個:
大型項(xiàng)目如何合理劃分組件模塊
當(dāng)項(xiàng)目的組件數(shù)量非常多的時候如何管理
第二個問題,可以通過Calces快速解決,至于第一個問題,筆者給出的指導(dǎo)就是,業(yè)務(wù)模塊在合理的情況下要盡可能的小,因?yàn)樵叫〉哪K,越容易達(dá)到高內(nèi)聚低耦合的目的。讀者不需要擔(dān)心項(xiàng)目模塊劃分得過于細(xì)不便于管理的問題,因?yàn)镃alces能夠輕松幫你管理好各個模塊。
最后分享我整理的騰訊T3級別的整套系統(tǒng)化的進(jìn)階視頻,對于有3到5年Android開發(fā)經(jīng)驗(yàn)的朋友深入學(xué)習(xí)提升幫助很大。有興趣的小伙伴可以加騰訊課堂的官方交流群;830344345。免費(fèi)學(xué)習(xí)下載。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/7039.html
摘要:最新最全的開源項(xiàng)目合集掘金是由整理并維護(hù)的安卓相關(guān)開源項(xiàng)目庫集合。準(zhǔn)備的插件開發(fā)必開發(fā)者福利史上最全開發(fā)和安全系列工具掘金取證工具一個工具箱,用于分析手機(jī)元數(shù)據(jù)。 最新最全的 Android 開源項(xiàng)目合集 - Android - 掘金awesome-github-android-ui 是由OpenDigg整理并維護(hù)的安卓UI相關(guān)開源項(xiàng)目庫集合。我們會定期同步OpenDigg上的項(xiàng)目到這...
摘要:讓你收獲滿滿碼個蛋從年月日推送第篇文章一年過去了已累積推文近篇文章,本文為年度精選,共計篇,按照類別整理便于讀者主題閱讀。本篇文章是今年的最后一篇技術(shù)文章,為了讓大家在家也能好好學(xué)習(xí),特此花了幾個小時整理了這些文章。 showImg(https://segmentfault.com/img/remote/1460000013241596); 讓你收獲滿滿! 碼個蛋從2017年02月20...
閱讀 769·2023-04-25 19:43
閱讀 4021·2021-11-30 14:52
閱讀 3855·2021-11-30 14:52
閱讀 3909·2021-11-29 11:00
閱讀 3838·2021-11-29 11:00
閱讀 3949·2021-11-29 11:00
閱讀 3613·2021-11-29 11:00
閱讀 6310·2021-11-29 11:00