在Android源碼中亿柑,最常用到的Builder模式的就是AlertDialog.Builder.
public class AlertDialog extends AppCompatDialog implements DialogInterface {
final AlertController mAlert; //用來接收Builder成員變量P中的各個(gè)參數(shù)
static final int LAYOUT_HINT_SIDE = 1;
protected AlertDialog(@NonNull Context context) {
this(context, 0);
}
protected AlertDialog(@NonNull Context context, @StyleRes int themeResId) {
super(context, resolveDialogTheme(context, themeResId));
mAlert = new AlertController(getContext(), this, getWindow());
}
......................省略代碼...................
@Override
public void setTitle(CharSequence title) {
super.setTitle(title);
//實(shí)際上是mAlert的setTitle方法
mAlert.setTitle(title);
}
Builder是AlertDialog 的內(nèi)部類
public static class Builder {
private final AlertController.AlertParams P;
private final int mTheme;
public Builder(@NonNull Context context) {
this(context, resolveDialogTheme(context, 0));
}
//設(shè)置各種參數(shù)
public Builder setView(View view) {
P.mView = view;
P.mViewLayoutResId = 0;
P.mViewSpacingSpecified = false;
return this;
}
//構(gòu)建AlertDialog邢疙,傳遞參數(shù)
public AlertDialog create() {
final AlertDialog dialog = new AlertDialog(P.mContext, mTheme);
//將p中的參數(shù)應(yīng)用到dialog的mAlert對(duì)象中
P.apply(dialog.mAlert);
dialog.setCancelable(P.mCancelable);
if (P.mCancelable) {
dialog.setCanceledOnTouchOutside(true);
}
dialog.setOnCancelListener(P.mOnCancelListener);
dialog.setOnDismissListener(P.mOnDismissListener);
if (P.mOnKeyListener != null) {
dialog.setOnKeyListener(P.mOnKeyListener);
}
return dialog;
}
}
上述代碼中,Builder設(shè)置AlertDialog中title、message疟游、button等參數(shù)呼畸,這些參數(shù)都存儲(chǔ)在AlertController.AlertParams P中,其中包含了與AlertDialog視圖中對(duì)應(yīng)的成員變量
看一下P.apply()方法
public void apply(AlertController dialog) {
if (mCustomTitleView != null) {
dialog.setCustomTitle(mCustomTitleView);
} else {
if (mTitle != null) {
dialog.setTitle(mTitle);
}
if (mIcon != null) {
dialog.setIcon(mIcon);
}
if (mIconId != 0) {
dialog.setIcon(mIconId);
}
if (mIconAttrId != 0) {
dialog.setIcon(dialog.getIconAttributeResId(mIconAttrId));
}
}
在apply函數(shù)中颁虐,只是將AlertParams 參數(shù)設(shè)置到AlertController中蛮原,例如,將標(biāo)題設(shè)置到Dialog對(duì)應(yīng)的標(biāo)題視圖中另绩,需要我們調(diào)用show()方法儒陨。
show()方法
public void show() {
if (mShowing) {
if (mDecor != null) {
if (mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
mWindow.invalidatePanelMenu(Window.FEATURE_ACTION_BAR);
}
mDecor.setVisibility(View.VISIBLE);
}
return;
}
mCanceled = false;
if (!mCreated) {
//來調(diào)用AlertDialog的oncreate()函數(shù)
dispatchOnCreate(null);
} else {
// Fill the DecorView in on any configuration changes that
// may have occured while it was removed from the WindowManager.
final Configuration config = mContext.getResources().getConfiguration();
mWindow.getDecorView().dispatchConfigurationChanged(config);
}
//調(diào)用Alert的onstart方法
onStart();
mDecor = mWindow.getDecorView();
if (mActionBar == null && mWindow.hasFeature(Window.FEATURE_ACTION_BAR)) {
final ApplicationInfo info = mContext.getApplicationInfo();
mWindow.setDefaultIcon(info.icon);
mWindow.setDefaultLogo(info.logo);
mActionBar = new WindowDecorActionBar(this);
}
WindowManager.LayoutParams l = mWindow.getAttributes();
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) == 0) {
WindowManager.LayoutParams nl = new WindowManager.LayoutParams();
nl.copyFrom(l);
nl.softInputMode |=
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION;
l = nl;
}
//將Dialog的DecorView添加到WindowManager中
mWindowManager.addView(mDecor, l);
mShowing = true;
sendShowMessage();
}
下面來看一下dispatchOnCreate()這個(gè)方法
void dispatchOnCreate(Bundle savedInstanceState) {
if (!mCreated) {
onCreate(savedInstanceState);//調(diào)用Dialog的oncreate,空方法笋籽, AlertDialog繼承Dialog蹦漠,其自身實(shí)現(xiàn)
mCreated = true;
}
}
AlertDialog的oncreate()方法
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAlert.installContent();
}
跳轉(zhuǎn)進(jìn)去,查看其方法
public void installContent() {
final int contentView = selectContentView();
mDialog.setContentView(contentView);
setupView();
}
調(diào)用setContentView和Activity的一樣车海,這里設(shè)置AlertDialog的內(nèi)容布局笛园,這個(gè)內(nèi)容布局就是mAlertDialogLayout字段的值,這個(gè)值在AlertController的構(gòu)造函數(shù)中進(jìn)行了初始化侍芝。
最后就是setupView()方法了研铆,初始化AlertDialog布局中各個(gè)部分,Dialog視圖部分設(shè)置完畢州叠。 當(dāng)用戶調(diào)用show()方法時(shí)棵红,WindowManager會(huì)將Window的DecorView(mAlertDialogLayout的視圖), mWindowManager.addView(mDecor, l);添加到用戶窗口上咧栗。
至此逆甜,Dialog就出現(xiàn)在用戶的視野中了。楼熄。忆绰。浩峡。可岂。