Android 設(shè)計(jì)模式(二)建造者模式
目錄:
傳統(tǒng)的建造者模式
Android中的建造者模式在AlertDialog中的應(yīng)用
PhoneWindow#setContentView源碼簡要分析

傳統(tǒng)的建造者模式
建造者模式也是常見的一種模式,它主要分成以下幾個(gè)角色:
抽象產(chǎn)品
具體產(chǎn)品:具體產(chǎn)品是抽象產(chǎn)品的子類
抽象建造者
具體建造者
Director:在Director中持有一個(gè)抽象創(chuàng)建者,并且返回一個(gè)抽象產(chǎn)品。傳入一個(gè)具體的創(chuàng)建者并且調(diào)用其構(gòu)建方法可以或返回一個(gè)具體的產(chǎn)品的實(shí)現(xiàn)。
代碼如下:
抽象產(chǎn)品
抽象建造者:
具體產(chǎn)品:
具體構(gòu)建者:
Director:

建造者模式在Android中的實(shí)現(xiàn):
我們主要通常使用的是構(gòu)建一個(gè)AlertDialog對象,不過構(gòu)建OkHttpClient也用到了構(gòu)建者模式。在Android中,AlertDialog將Builder和Director的職能結(jié)合,通過在每次setXX返回一個(gè)builder實(shí)例,實(shí)現(xiàn)了一個(gè)鏈?zhǔn)秸{(diào)用的形式:
AlertDialog也是一個(gè)window,我們著力在AlertDialog和window上做分析。
AlertDialog的構(gòu)造函數(shù)
可以看到AlertDialog通過AlertController#create構(gòu)建了一個(gè)AlertController的實(shí)例。實(shí)際上AlertDialog的設(shè)計(jì)相當(dāng)好,AlertDialog視圖的顯示就是通過AlertController這個(gè)控制器。
在create中,還通過getWindow傳入了一個(gè)Window對象:
Window在AlertDialog父類的構(gòu)造函數(shù)中創(chuàng)建了一個(gè)PhoneWindow對象,并且獲取了WMS。WMS也是上一章分析過的一個(gè)從Map容器中獲取的單例:

我們回到我們的流程中,去看看內(nèi)部類Builder相關(guān)的實(shí)現(xiàn):
差不多setTitle,setText都是這樣的形式。
然后再是Builder#create過程:
因?yàn)锳lert的視圖顯示都是交給自身的AlertController,我們主要看看AlertControler.Params#apply:
這里還是一個(gè)職能充分解耦的體現(xiàn),和參數(shù)相關(guān)的操作都交給AlertController.Params完成。AlertController中的setXXX才是真正的和定義在alert_dialog.xml中的View交互的過程:
mMessageView通過findViewById實(shí)例化,然后設(shè)置Text,其他的set操作也類似。
Dialog#show
最后的流程就是Dialog#show
show流程大概分成這樣的幾個(gè)部分,使用圖表示:

先不看和生命周期流程相關(guān)的onCreate和onStart,在onStart之后會從Window中獲取DecorView,然后使用WindowManager#addView。WindowManager#addView的過程有點(diǎn)復(fù)雜,在這篇文章Android UI體系中有說過,這里不重復(fù)。
我們主要現(xiàn)在主要看看dispatchOnCreate。dispatchOnCreate會調(diào)用onCreate
AlertController#installContent
這里看到了熟悉的setContentView,在Activity#setContent最后也會調(diào)用這里的PhoneWindow#setContentView,這里簡要做一個(gè)分析:
setContentView主要是installDecor這一步,installDecor包括創(chuàng)建DecorView和mContentParent兩個(gè)過程,代碼調(diào)用鏈如下:

從圖中可以看出,DecorView在定義中包括TitleView和ContentView兩個(gè)部分,ContentView就是我們使用resId填充的部分:

最后是sendShowMessage方法:
showMessage攜帶的obj就是一個(gè)OnShow的回調(diào),disMiss和cancel的回調(diào)就是我們設(shè)置的