起因
? 最近一直在做Android框架方面的工作,先是把原來的網(wǎng)絡(luò)框架由Netroid改為了Retrofit+Rxjava,然后在這次修改的基礎(chǔ)上,有做了大量的基礎(chǔ)的Activity和Fragment的封裝,以及對應(yīng)的MVP的架構(gòu)封裝,也是經(jīng)過多次修改調(diào)整后,基本成型了,隨后單開一篇文章介紹這個(gè)Android架構(gòu),這個(gè)架構(gòu)適合小項(xiàng)目,小團(tuán)隊(duì)使用,也是根據(jù)網(wǎng)上的大牛提供的思路,自己實(shí)踐來的,經(jīng)過幾次進(jìn)化后,應(yīng)付中小項(xiàng)目應(yīng)該是綽綽有余了。
? 中小型項(xiàng)目框架涵蓋的關(guān)鍵字:MVP、Retrofit、RXAndroid、RxAndroidLifeCycle、EventBus、LitePal、CommonUtils(涵蓋非常全面的工具類庫)等。
有句話說的好:既得隴,復(fù)望蜀。
? 在中小型項(xiàng)目的框架成功后,我覺得不如就此機(jī)會把組件化的架構(gòu)一并實(shí)現(xiàn),于是就開始學(xué)習(xí)組件化的架構(gòu)組織,一步一步的把自己的項(xiàng)目架構(gòu)慢慢的轉(zhuǎn)成了組件化的開發(fā),不過目前還沒有完成,有幾個(gè)問題需要處理:
- 引入路由組件
- 封裝常用的自定義View
- 封裝業(yè)務(wù)組件:通用Dialog,通用RecycleView、通用進(jìn)度條等,這個(gè)就很隨意了,主要還是看開發(fā)者自己的主觀意愿。
? 在初步的完成了封裝后,發(fā)現(xiàn)了一個(gè)問題,就是我把原來在單一項(xiàng)目框架下的源碼轉(zhuǎn)移到了組件化框架下的子業(yè)務(wù)框架下,說白了就是在組件化開啟的前提下,把源碼從App轉(zhuǎn)移到了Library下,從理論上來說,應(yīng)該不會有什么問題,但是歷史實(shí)踐告訴我們,理論往往是靠不住的,在轉(zhuǎn)移的過程中,我就遇到了ButterKnife造成的問題。
問題
下面我們來看一下具體的問題:

如果你強(qiáng)制編譯,Build控制臺就會很貼心的用中文再告訴你一次:

元素值必須為常量表達(dá)式?怎么就不是常量了?!我們知道R.id.XX其實(shí)就是引入了R文件中的一個(gè)靜態(tài)常量,所謂的靜態(tài)常量其實(shí)就是static final的中文說法,于是我點(diǎn)開了R文件:

好吧,沒有final.......正常的Application中的R文件應(yīng)該是這樣的:

為什么缺少了final關(guān)鍵字呢?原因其實(shí)谷歌已經(jīng)給出了:
從ADT14開始Library中的R文件才從靜態(tài)常量變?yōu)榉浅A?因?yàn)槿绻诙鄠€(gè)Library中可能出現(xiàn)id沖突的問題.在ADT14以前則采用的是將所有的資源文件和相關(guān)的代碼重新隨著主項(xiàng)目一起編譯,導(dǎo)致編譯速度過慢.因此,從ADT14開始就變成了非常量的id了。
雖然這個(gè)改動(dòng)的出發(fā)點(diǎn)是好的,但是隨著組件化越來越普及,業(yè)務(wù)組件放在library的情況會越來越多,ButterKnife需要在Library中使用的情況也越來越多,所以,JakeWharton大神終于在大家的呼喚下,讓ButterKnife支持Library了。
解決
官方的解決方案:

第一步
在項(xiàng)目的build.gradle中的dependencies中加入:classpath 'com.jakewharton:butterknife-gradle-plugin:9.0.0-rc1'
第二步
在業(yè)務(wù)子Library的Build.gradle中加入:apply plugin: 'com.jakewharton.butterknife'
這里要注意:
if (isModule.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
apply plugin: 'com.jakewharton.butterknife'
不論你是否開啟組件化,都要把這個(gè)插件加入進(jìn)去。
第三步
這里要注意了,敲黑板!
如果你的ButterKnife的依賴是集成在本業(yè)務(wù)Library中的,那你就不用管我下面說的話了,如果不是,一定要看仔細(xì)!
我的ButterKnife就不是封裝在本業(yè)務(wù)的Library中的,而是在其底層的一個(gè)名為BaseLib的Library中引入的,該Library主要是提供BaseActivity和BaseFragment等基礎(chǔ)組件的,在該Library中引入也是為了合理的處理所有ButterKnife的解綁操作,那么這時(shí),如果你要在你的業(yè)務(wù)Library中使用ButterKnife,你不必重復(fù)引入ButterKnife的依賴,而是在業(yè)務(wù)Library中加入:
dependencies {
api project(':BaseLib')
//這里要將ButterKnife的注解加入主項(xiàng)目中去,因?yàn)樽禹?xiàng)目無法通過api引入
annotationProcessor "com.jakewharton:butterknife-compiler:$butterknife_version"
}
否則就會出現(xiàn)一個(gè)問題,那就是你的項(xiàng)目在編譯時(shí)不會報(bào)錯(cuò),但是在運(yùn)行時(shí)就會報(bào)空指針的錯(cuò)誤:
2018-10-26 16:33:50.166 15872-15872/? W/System.err: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.xxx.read/com.xxx.read.ReadActivityMainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.view.View.setVisibility(int)' on a null object reference
2018-10-26 16:33:50.167 15872-15872/? W/System.err: at com.dhcc.commonutils.BarUtils.setStatusBarAlpha(BarUtils.java:294)
2018-10-26 16:33:50.167 15872-15872/? W/System.err: at com.dhcc.commonutils.BarUtils.setStatusBarAlpha4Drawer(BarUtils.java:385)
2018-10-26 16:33:50.167 15872-15872/? W/System.err: at com.dhcc.read.ReadActivityMainActivity.initView(ReadActivityMainActivity.java:95)
2018-10-26 16:33:50.167 15872-15872/? W/System.err: at com.dhcc.baseLib.base.activity.BaseActivity.onCreate(BaseActivity.java:51)
2018-10-26 16:33:50.167 15872-15872/? W/System.err: at com.dhcc.read.ReadActivityMainActivity.onCreate(ReadActivityMainActivity.java:228)
這個(gè)問題比較特殊,并不是所有人都會遇到,如果你遇到了,記得按照我這樣處理,就可以了。
第四步
把業(yè)務(wù)Library項(xiàng)目中的所有關(guān)于ButterKnife的R引用,改為R2引用即可。
如:
@BindView(R2.id.toolbar)
Toolbar toolbar;
@BindView(R2.id.fake_status_bar)
View fakeStatusBar;
@BindView(R2.id.textView)
TextView textView;
這里注意一下,并不是所有的R文件都改成R2,如果是R.layout這類R引用就不要更改,保持原狀即可,否則會在運(yùn)行時(shí)報(bào)出找不到View的指定ID的錯(cuò)誤。
如:
/**
* 綁定布局
*
* @return 布局 Id
*/
@Override
public int bindLayout() {
return R.layout.read_activity_main;
}
總結(jié)
任何一個(gè)架構(gòu)的形成都有門檻,有坑,有知識,有趣,我不愿意做那種被安排的程序員,所以,這些坑其實(shí)都是我的樂趣所在,今天拿出我的趟坑經(jīng)驗(yàn)分享給大家,是希望看到的朋友可以走的比我更遠(yuǎn)。
謝謝你的閱讀。