Android組件化開發(fā)

一.什么是組件化開發(fā)

所謂組件化,就是將整個龐大的項目以業(yè)務(wù)邏輯進行拆分成多個模塊,并且各個模塊之間相互獨立,相互解耦,每一個模塊可以單獨進行開發(fā)調(diào)試,各個模塊調(diào)試完,以library的形式依賴在殼App中組合成一個完整的項目。

二.為什么要采用組件化

隨著APP版本不斷的迭代,新功能的不斷增加,業(yè)務(wù)也會變的越來越復(fù)雜,APP業(yè)務(wù)模塊的數(shù)量有可能還會繼續(xù)增加,而且每個模塊的代碼也變的越來越多,這樣發(fā)展下去單一工程下的APP架構(gòu)勢必會影響開發(fā)效率,增加項目的維護成本,每個工程師都要熟悉如此之多的代碼,將很難進行多人協(xié)作開發(fā),而且Android項目在編譯代碼的時候電腦會非???,又因為單一工程下代碼耦合嚴(yán)重,每修改一處代碼后都要重新編譯打包測試,導(dǎo)致非常耗時,最重要的是這樣的代碼想要做單元測試根本無從下手,所以必須要有更靈活的架構(gòu)代替過去單一的工程架構(gòu)。

單一工程:原先采用的架構(gòu)

從圖中我們可以看出,單一工程的話,所有的業(yè)務(wù)邏輯都整合再同一個app中,業(yè)務(wù)邏輯之間也相互依賴,所謂的你中有我,我中有你,相互依賴,無法分離。單一工程也存在以下幾個問題:

1、實際業(yè)務(wù)變化非???,但是單一工程的業(yè)務(wù)模塊耦合度太高,牽一發(fā)而動全身;

2、對工程所做的任何修改都必須要編譯整個工程;

3、功能測試和系統(tǒng)測試每次都要進行;

4、團隊協(xié)同開發(fā)存在較多的沖突.不得不花費更多的時間去溝通和協(xié)調(diào),并且在開發(fā)過程中,任何一位成員沒辦法專注于自己的功能點,影響開發(fā)效率;

5、不能靈活的對業(yè)務(wù)模塊進行配置和組裝;

因此,為了滿足各個業(yè)務(wù)模塊的迭代而彼此不受影響,更好的解決上面這種讓人頭疼的依賴關(guān)系,我們就需要整改app架構(gòu)。

組件化工程:整改后的架構(gòu)

幾個名詞解釋:

集成模式:所有的業(yè)務(wù)組件被“app殼工程”依賴,組成一個完整的APP;

組件模式:可以獨立開發(fā)業(yè)務(wù)組件,每一個業(yè)務(wù)組件就是一個APP;

app殼工程:負(fù)責(zé)管理各個業(yè)務(wù)組件,和打包apk,沒有具體的業(yè)務(wù)功能;

業(yè)務(wù)組件:根據(jù)公司具體業(yè)務(wù)而獨立形成一個的工程;

功能組件:提供開發(fā)APP的某些基礎(chǔ)功能,例如打印日志、樹狀圖等;

BaseModule組件:屬于功能組件,支撐業(yè)務(wù)組件的基礎(chǔ),提供多數(shù)業(yè)務(wù)組件需要的功能,例如提供網(wǎng)絡(luò)請求功能;

Android APP組件化架構(gòu)的目標(biāo)是告別結(jié)構(gòu)臃腫,讓各個業(yè)務(wù)變得相對獨立,業(yè)務(wù)組件在組件模式下可以獨立開發(fā),而在集成模式下又可以變?yōu)閍rr包集成到“app殼工程”中,組成一個完整功能的APP;
從組件化工程模型中可以看到,業(yè)務(wù)組件之間是獨立的,沒有關(guān)聯(lián)的,這些業(yè)務(wù)組件在集成模式下是一個個library,被app殼工程所依賴,組成一個具有完整業(yè)務(wù)功能的APP應(yīng)用,但是在組件開發(fā)模式下,業(yè)務(wù)組件又變成了一個個application,它們可以獨立開發(fā)和調(diào)試,由于在組件開發(fā)模式下,業(yè)務(wù)組件們的代碼量相比于完整的項目差了很遠,因此在運行時可以顯著減少編譯時間。

這是組件化工程模型下的業(yè)務(wù)關(guān)系,業(yè)務(wù)之間將不再直接引用和依賴,而是通過“路由”這樣一個中轉(zhuǎn)站間接產(chǎn)生聯(lián)系,而Android中的路由實際就是對URL Scheme的封裝;

組件化開發(fā)可以帶來以下優(yōu)勢:

1、加快業(yè)務(wù)迭代速度,各個業(yè)務(wù)模塊組件更加獨立,不再出現(xiàn)業(yè)務(wù)耦合情況;

2、穩(wěn)定的公共模塊采用依賴庫方式,提供給各個業(yè)務(wù)線使用,減少重復(fù)開發(fā)和維護工作量;

3、迭代頻繁的業(yè)務(wù)模塊采用組件方式,各業(yè)務(wù)研發(fā)可以互不干擾、提升協(xié)作效率,并控制產(chǎn)品質(zhì)量;

4、為新業(yè)務(wù)隨時集成提供了基礎(chǔ),所有業(yè)務(wù)可上可下,靈活多變;

5、降低團隊成員熟悉項目的成本,降低項目的維護難度;

6、加快編譯速度,提高開發(fā)效率;

7、控制代碼權(quán)限,將代碼的權(quán)限細分到更小的粒度;

三、組件化具體實現(xiàn)

前言:需要先確定業(yè)務(wù)模塊的劃分,定義一些全局的變量,來控制模塊不同模式的切換。

前期準(zhǔn)備:

1)組件模式和集成模式的轉(zhuǎn)換

AndroidStudio中的Module主要有兩種屬性,分別為:

1、application屬性,可以獨立運行的應(yīng)用程序,就是一個app

apply plugin: ‘com.android.application’

2.library屬性,不可以單獨運行,一般是依賴的庫文件

apply plugin: ‘com.android.library’

Module的屬性是在每個組件的 build.gradle 文件中配置的,當(dāng)我們在組件模式開發(fā)時,業(yè)務(wù)組件應(yīng)處于application屬性,這時的業(yè)務(wù)組件就是一個 Android App,可以獨立開發(fā)和調(diào)試;而當(dāng)我們轉(zhuǎn)換到集成模式開發(fā)時,業(yè)務(wù)組件應(yīng)該處于 library 屬性,這樣才能被我們的“app殼工程”所依賴,組成一個具有完整功能的APP;

但是我們?nèi)绾巫尳M件在這兩種模式之間自動轉(zhuǎn)換呢?總不能每次需要轉(zhuǎn)換模式的時候去每個業(yè)務(wù)組件的 Gralde 文件中去手動把 Application 改成 library 吧?如果我們的項目只有兩三個組件那么這個辦法肯定是可行的,手動去改一遍也用不了多久,但是在大型項目中我們可能會有十幾個業(yè)務(wù)組件,再去手動改一遍必定費時費力,這時候就需要程序員發(fā)揮下懶的本質(zhì)了。

試想,我們經(jīng)常在寫代碼的時候定義靜態(tài)常量,那么定義靜態(tài)常量的目的什么呢?當(dāng)一個常量需要被好幾處代碼引用的時候,把這個常量定義為靜態(tài)常量的好處是當(dāng)這個常量的值需要改變時我們只需要改變靜態(tài)常量的值,其他引用了這個靜態(tài)常量的地方都會被改變,做到了一次改變,到處生效;根據(jù)這個思想,那么我們就可以在我們的代碼中的某處定義一個決定業(yè)務(wù)組件屬性的常量,然后讓所有業(yè)務(wù)組件的build.gradle都引用這個常量,這樣當(dāng)我們改變了常量值的時候,所有引用了這個常量值的業(yè)務(wù)組件就會根據(jù)值的變化改變自己的屬性;可是問題來了?靜態(tài)常量是用Java代碼定義的,而改變組件屬性是需要在Gradle中定義的,Gradle能做到嗎?

Gradle自動構(gòu)建工具有一個重要屬性,可以幫助我們完成這個事情。每當(dāng)我們用AndroidStudio創(chuàng)建一個Android項目后,就會在項目的根目錄中生成一個文件 gradle.properties,我們將使用這個文件的一個重要屬性:在Android項目中的任何一個build.gradle文件中都可以把gradle.properties中的常量讀取出來;那么我們在上面提到解決辦法就有了實際行動的方法,首先我們在gradle.properties中定義一個常量值 isModule(是否是組件開發(fā)模式,true為是,false為否):

# 每次更改“isModule”的值后,需要點擊 "Sync Project" 按鈕#不能用;結(jié)束isModule = true

然后我們在每一個業(yè)務(wù)組件的build.gradle中讀取 isModule,但是 gradle.properties 還有一個重要屬性: gradle.properties 中的數(shù)據(jù)類型都是String類型,使用其他數(shù)據(jù)類型需要自行轉(zhuǎn)換;也就是說我們讀到 isModule 是個String類型的值,而我們需要的是Boolean值,代碼如下:在模塊build.gradle中

if(isModule.toBoolean()){//如果是組件模式---可以單獨運行    apply plugin: 'com.android.application'}else {//集成模式,不能單獨運行    apply plugin: 'com.android.library'}

這樣我們第一個問題就解決了,當(dāng)然了 每次改變isModule的值后,都要同步項目才能生效;

2)組件之間AndroidManifest合并問題

在 AndroidStudio 中每一個組件都會有對應(yīng)的 AndroidManifest.xml,用于聲明需要的權(quán)限、Application、Activity、Service、Broadcast等,當(dāng)項目處于組件模式時,業(yè)務(wù)組件的 AndroidManifest.xml 應(yīng)該具有一個 Android APP 所具有的的所有屬性,尤其是聲明 Application 和要 launch的Activity,但是當(dāng)項目處于集成模式的時候,每一個業(yè)務(wù)組件的 AndroidManifest.xml 都要合并到“app殼工程”中,要是每一個業(yè)務(wù)組件都有自己的 Application 和 launch的Activity,那么合并的時候肯定會沖突,試想一個APP怎么可能會有多個 Application 和 launch 的Activity呢?

但是大家應(yīng)該注意到這個問題是在組件開發(fā)模式和集成開發(fā)模式之間轉(zhuǎn)換引起的問題,而在上一節(jié)中我們已經(jīng)解決了組件模式和集成模式轉(zhuǎn)換的問題,另外大家應(yīng)該都經(jīng)歷過將 Android 項目從 Eclipse 切換到 AndroidStudio 的過程,由于 Android 項目在 Eclipse 和 AndroidStudio開發(fā)時 AndroidManifest.xml 文件的位置是不一樣的,我們需要在build.gradle 中指定下 AndroidManifest.xml 的位置,AndroidStudio 才能讀取到 AndroidManifest.xml,這樣解決辦法也就有了,我們可以為組件開發(fā)模式下的業(yè)務(wù)組件再創(chuàng)建一個 AndroidManifest.xml,然后根據(jù)isModule指定AndroidManifest.xml的文件路徑,讓業(yè)務(wù)組件在集成模式和組件模式下使用不同的AndroidManifest.xml,這樣表單沖突的問題就可以規(guī)避了。

上圖是組件化項目中一個標(biāo)準(zhǔn)的業(yè)務(wù)組件目錄結(jié)構(gòu),首先我們在main文件夾下創(chuàng)建一個module文件夾用于存放組件開發(fā)模式下業(yè)務(wù)組件的 AndroidManifest.xml,而 AndroidStudio 生成的 AndroidManifest.xml 則依然保留,并用于集成開發(fā)模式下業(yè)務(wù)組件的表單;然后我們需要在業(yè)務(wù)組件的 build.gradle 中指定表單的路徑,代碼如下:

這樣在不同的開發(fā)模式下就會讀取到不同的 AndroidManifest.xml ,然后我們需要修改這兩個表單的內(nèi)容以為我們不同的開發(fā)模式服務(wù)。

首先是集成開發(fā)模式下的 AndroidManifest.xml,前面我們說過集成模式下,業(yè)務(wù)組件的表單是絕對不能擁有自己的 Application 和 launch 的 Activity的,也不能聲明APP名稱、圖標(biāo)等屬性,總之a(chǎn)pp殼工程有的屬性,業(yè)務(wù)組件都不能有,下面是一份標(biāo)準(zhǔn)的集成開發(fā)模式下業(yè)務(wù)組件的 AndroidManifest.xml:

我在這個表單中只聲明了應(yīng)用的主題,而且這個主題還是跟app殼工程中的主題是一致的,都引用了BaseModule組件中的資源文件,在這里聲明主題是為了方便這個業(yè)務(wù)組件中有使用默認(rèn)主題的Activity時就不用再給Activity單獨聲明theme了。

然后是組件開發(fā)模式下的表單文件:

組件模式下的業(yè)務(wù)組件表單就是一個Android項目普通的AndroidManifest.xml,這里就不在過多介紹了。

3)全局Context的獲取及組件數(shù)據(jù)初始化

當(dāng)Android程序啟動時,Android系統(tǒng)會為每個程序創(chuàng)建一個 Application 類的對象,并且只創(chuàng)建一個,application對象的生命周期是整個程序中最長的,它的生命周期就等于這個程序的生命周期。在默認(rèn)情況下應(yīng)用系統(tǒng)會自動生成 Application 對象,但是如果我們自定義了 Application,那就需要在 AndroidManifest.xml 中聲明告知系統(tǒng),實例化的時候,是實例化我們自定義的,而非默認(rèn)的。

但是我們在組件化開發(fā)的時候,可能為了數(shù)據(jù)的問題每一個組件都會自定義一個Application類,如果我們在自己的組件中開發(fā)時需要獲取 全局的Context,一般都會直接獲取 application 對象,但是當(dāng)所有組件要打包合并在一起的時候就會出現(xiàn)問題,因為最后程序只有一個 Application,我們組件中自己定義的 Application 肯定是沒法使用的,因此我們需要想辦法再任何一個業(yè)務(wù)組件中都能獲取到全局的 Context,而且這個 Context 不管是在組件開發(fā)模式還是在集成開發(fā)模式都是生效的。

在 組件化工程模型圖中,功能組件集合中有一個 BaseModule組件, BaseModule有公共、公用、共同的意思,所以這個組件中主要封裝了項目中需要的基礎(chǔ)功能,并且每一個業(yè)務(wù)組件都要依賴BaseModule組件,BaseModule組件就像是萬丈高樓的地基,而業(yè)務(wù)組件就是在 BaseModule組件這個地基上搭建起來我們的APP的,BaseModule組件會專門在一個章節(jié)中講解,這里只講 BaseModule組件中的一個功能,在BaseModule組件中我們封裝了項目中用到的各種Base類,這些基類中就有BaseApplication 類。

BaseApplication 主要用于各個業(yè)務(wù)組件和app殼工程中聲明的 Application 類繼承用的,只要各個業(yè)務(wù)組件和app殼工程中聲明的Application類繼承了 BaseApplication,當(dāng)應(yīng)用啟動時 BaseApplication 就會被動實例化,這樣從 BaseApplication 獲取的 Context 就會生效,也就從根本上解決了我們不能直接從各個組件獲取全局 Context 的問題;

這時候大家肯定都會有個疑問?不是說了業(yè)務(wù)組件不能有自己的 Application 嗎,怎么還讓他們繼承 BaseApplication 呢?其實我前面說的是業(yè)務(wù)組件不能在集成模式下?lián)碛凶约旱?Application,但是這不代表業(yè)務(wù)組件也不能在組件開發(fā)模式下?lián)碛凶约旱腁pplication,其實業(yè)務(wù)組件在組件開發(fā)模式下必須要有自己的 Application 類,一方面是為了讓 BaseApplication 被實例化從而獲取 Context,還有一個作用是,業(yè)務(wù)組件自己的 Application 可以在組件開發(fā)模式下初始化一些數(shù)據(jù),例如在組件開發(fā)模式下,A組件沒有登錄頁面也沒法登錄,因此就無法獲取到 Token,這樣請求網(wǎng)絡(luò)就無法成功,因此我們需要在A組件這個 APP 啟動后就應(yīng)該已經(jīng)登錄了,這時候組件自己的 Application 類就有了用武之地,我們在組件的 Application的 onCreate 方法中模擬一個登陸接口,在登陸成功后將數(shù)據(jù)保存到本地,這樣就可以處理A組件中的數(shù)據(jù)業(yè)務(wù)了;另外我們也可以在組件Application中初始化一些第三方庫

但是,實際上業(yè)務(wù)組件中的Application在最終的集成項目中是沒有什么實際作用的,組件自己的 Application 僅限于在組件模式下發(fā)揮功能,因此我們需要在將項目從組件模式轉(zhuǎn)換到集成模式后將組件自己的Application剔除出我們的項目;在 AndroidManifest 合并問題小節(jié)中介紹了如何在不同開發(fā)模式下讓 Gradle 識別組件表單的路徑,這個方法也同樣適用于Java代碼;

我們在Java文件夾下創(chuàng)建一個 debug 文件夾,用于存放不會在業(yè)務(wù)組件中引用的類,例如上圖中的 NewsApplication ,你甚至可以在 debug 文件夾中創(chuàng)建一個Activity,然后組件表單中聲明啟動這個Activity,在這個Activity中不用setContentView,只需要在啟動你的目標(biāo)Activity的時候傳遞參數(shù)就行,這樣就就可以解決組件模式下某些Activity需要getIntent數(shù)據(jù)而沒有辦法拿到的情況.

接下來在業(yè)務(wù)組件的 build.gradle 中,根據(jù) isModule 是否是集成模式將 debug 這個 Java代碼文件夾排除:

4)library依賴問題

在介紹這一節(jié)的時候,先說一個問題,在組件化工程模型圖中,多媒體組件和BaseModule組件都依賴了日志組件,而A業(yè)務(wù)組件有同時依賴了多媒體組件和BaseModule組件,這時候就會有人問,你這樣搞豈不是日志組件要被重復(fù)依賴了,而且BaseModule組件也被每一個業(yè)務(wù)組件依賴了,這樣不出問題嗎?

其實大家完全沒有必要擔(dān)心這個問題,如果真有重復(fù)依賴的問題,在你編譯打包的時候就會報錯,如果你還是不相信的話可以反編譯下最后打包出來的APP,看看里面的代碼你就知道了。組件只是我們在代碼開發(fā)階段中為了方便叫的一個術(shù)語,在組件被打包進APP的時候是沒有這個概念的,這些組件最后都會被打包成arr包,然后被app殼工程所依賴,在構(gòu)建APP的過程中Gradle會自動將重復(fù)的arr包排除,APP中也就不會存在相同的代碼了;

但是雖然組件是不會重復(fù)了,但是我們還是要考慮另一個情況,我們在build.gradle中compile的第三方庫,例如AndroidSupport庫經(jīng)常會被一些開源的控件所依賴,而我們自己一定也會compile AndroidSupport庫 ,這就會造成第三方包和我們自己的包存在重復(fù)加載,解決辦法就是找出那個多出來的庫,并將多出來的庫給排除掉,而且Gradle也是支持這樣做的,分別有兩種方式:根據(jù)組件名排除或者根據(jù)包名排除,下面以排除support-v4庫為例:

dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile("com.jude:easyrecyclerview:$rootProject.easyRecyclerVersion") { exclude module: 'support-v4'//根據(jù)組件名排除 exclude group: 'android.support.v4'//根據(jù)包名排除 } }

library重復(fù)依賴的問題算是都解決了,但是我們在開發(fā)項目的時候會依賴很多開源庫,而這些庫每個組件都需要用到,要是每個組件都去依賴一遍也是很麻煩的,尤其是給這些庫升級的時候,為了方便我們統(tǒng)一管理第三方庫,我們將給給整個工程提供統(tǒng)一的依賴第三方庫的入口,前面介紹的BaseModule庫的作用之一就是統(tǒng)一依賴開源庫,因為其他業(yè)務(wù)組件都依賴了BaseModule庫,所以這些業(yè)務(wù)組件也就間接依賴了BaseModule所依賴的開源庫。

dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) //Android Support compile "com.android.support:appcompat-v7:$rootProject.supportLibraryVersion" compile "com.android.support:design:$rootProject.supportLibraryVersion" compile "com.android.support:percent:$rootProject.supportLibraryVersion" //網(wǎng)絡(luò)請求相關(guān) compile "com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion" compile "com.squareup.retrofit2:retrofit-mock:$rootProject.retrofitVersion" compile "com.github.franmontiel:PersistentCookieJar:$rootProject.cookieVersion" //穩(wěn)定的 compile "com.github.bumptech.glide:glide:$rootProject.glideVersion" compile "com.orhanobut:logger:$rootProject.loggerVersion" compile "org.greenrobot:eventbus:$rootProject.eventbusVersion" compile "com.google.code.gson:gson:$rootProject.gsonVersion" compile "com.github.chrisbanes:PhotoView:$rootProject.photoViewVersion"  compile "com.jude:easyrecyclerview:$rootProject.easyRecyclerVersion" compile "com.github.GrenderG:Toasty:$rootProject.toastyVersion"  //router compile "com.github.mzule.activityrouter:activityrouter:$rootProject.routerVersion" }

然后將所有的具體版本號提取出來,放到根目錄的build.gradle文件中,統(tǒng)一管理

image

5)組件之間調(diào)用和通信

在組件化開發(fā)的時候,組件之間是沒有依賴關(guān)系,我們不能在使用顯示調(diào)用來跳轉(zhuǎn)頁面了,因為我們組件化的目的之一就是解決模塊間的強依賴問題,假如現(xiàn)在要從A業(yè)務(wù)組件跳轉(zhuǎn)到業(yè)務(wù)B組件,并且要攜帶參數(shù)跳轉(zhuǎn),這時候怎么辦呢?而且組件這么多怎么管理也是個問題,這時候就需要引入“路由”的概念了,由本文開始的組件化模型下的業(yè)務(wù)關(guān)系圖可知路由就是起到一個轉(zhuǎn)發(fā)的作用。

本文主要采用阿里的開元框架ARouter路由來實現(xiàn)組建之間的調(diào)用和通信。ARouter的詳細使用請前往https://mp.csdn.net/console/editor/html/104569796

ARouter各個模塊的gradle配置

  • 因為路由跳轉(zhuǎn)是子模塊都需要用到的,所以我們在BaseModule 模塊build.gradle中引入
    defaultConfig {        //ARouter添加        javaCompileOptions {            annotationProcessorOptions {                arguments = [moduleName: project.getName()]            }        }....} dependencies {api "com.alibaba:arouter-api:$rootProject.ext.arouterApiVersion"http://跳轉(zhuǎn)路由 } $rootProject.ext.arouterApiVersion == 1.3.1
  • 然后在各業(yè)務(wù)模塊的build.gradle文件中導(dǎo)入
    defaultConfig {
        //ARouter添加
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [moduleName: project.getName()]
            }
        }
....
}
 
dependencies {
    annotationProcessor "com.alibaba:arouter-compiler:$rootProject.ext.arouterCompilerVersion"
}
 
$rootProject.ext.arouterCompilerVersion == 1.1.4

組件之間的調(diào)用解決后,另外需要解決的就是組件之間的通信,例如A業(yè)務(wù)組件中有消息列表,而用戶在B組件中操作某個事件后會產(chǎn)生一條新消息,需要通知A組件刷新消息列表,這樣業(yè)務(wù)場景需求可以使用Android廣播來解決,也可以使用第三方的事件總線來實現(xiàn),比如RXBus。

ARouter的具體使用:

初始化

官方建議我們在Application里面進行ARouter初始化,于是乎就有了以下代碼:

@Override
public void onCreate() {
    super.onCreate();        
    if (LogUtils.isDebuggable()){//下面2行必須在init前面
        ARouter.openDebug();//開啟調(diào)試模式
        ARouter.openLog();//打印日志
    }
    ARouter.init(BaseApplication.this);
}
@Override
public void onTerminate() {
   super.onTerminate();
   //ARouter銷毀
   ARouter.getInstance().destroy();
}

然后別忘記了在清單文件里面配置自定義的Application和我們的Activity。

項目依賴導(dǎo)入和初始化就已經(jīng)完成了,下面就開始正式的功能使用以及簡單的封裝。

開始使用:

1)首先:在Activity/Fragment類上面寫上 Route path 注解。

  注意:這里的路徑需要注意的是至少需要有兩級,/xx/xx

2)然后:在Activity/Fragment類里面進入Arouter 注入,也就是:ARouter.getInstance().inject(this);

3)接著:目標(biāo)的Activity類上面需要聲明Route path 注解,以此對應(yīng)

 ARouter.getInstance().build(ConstanceURl.Home_Main).navigation();

傳遞參數(shù)

UrUtils2 urUtils2 = new UrUtils2();
urUtils2.setName1("對象名字");
urUtils2.setNum1(1);
ARouter.getInstance().build(ConstanceURl.Find_Main)
       .withString("name","名字1")
       .withInt("num",2)
       .withObject("test",urUtils2).navigation();

接受

路徑管理

界面跳轉(zhuǎn)動畫

直接調(diào)用withTransition,里面?zhèn)魅雰蓚€動畫即可(R.anim.xxx)

使用URI進行跳轉(zhuǎn)

ARouter框架也可以使用URI進行匹配跳轉(zhuǎn),代碼也很少,只需匹配路徑一致即可完成跳轉(zhuǎn):

Fragment跳轉(zhuǎn)

Fragment的跳轉(zhuǎn)也可以參照Activity跳轉(zhuǎn),第一步依舊是先寫上類注釋,然后是強轉(zhuǎn),代碼如下

ARouter如何實現(xiàn)類似startActivityForResult()?

返回

6)ButterKnife的引入

在更目錄build.gradle中引入依賴

classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.1'

在BaseModule添加build.gradle中引入依賴

//ButterKnife
    api "com.jakewharton:butterknife:$rootProject.ext.butterknifeVersion"
    annotationProcessor "com.jakewharton:butterknife-compiler:$rootProject.ext.butterknifeCompilerVersion"
 
$rootProject.ext.butterknifeVersion  == 10.2.1 
$rootProject.ext.butterknifeCompilerVersion == 10.2.1 

在每個業(yè)務(wù)模塊build.gradle中引入依賴

// 必須引入,否則會生成不了R2.class
apply plugin: 'com.jakewharton.butterknife'
 
 
annotationProcessor "com.jakewharton:butterknife-compiler:$rootProject.ext.butterknifeCompilerVersion"

在每一個Module(業(yè)務(wù)模塊,功能模塊,Main模塊,殼app模塊)都要在build.gradle中添加java8的支持

android{
    .....
     compileOptions{
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

使用:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容