設計模式-Builder模式(一)
一,builder模式簡介
- 定義 將一個複雜物件的構建與他的表示分離,使得同樣的構建過程可以建立不同的表示。
- 使用場景
(1)相同的方法,不同的執行順序,產生不同的事件結果 (2)多個部件或零件,都可以裝配到一個物件,但是產生的執行結果不相同 (3)產品類非常複雜 (4)當初始化一個物件特別複雜,如引數多,且很多引數都具有預設值時
二,Android原始碼分析_AlertDialog
- 例項
AlertDialog.Builder builder=new AlertDialog.Builder(this);
builder.setTitle("Titile"); builder.setIcon(R.mipmap.ic_launcher); builder.setPositiveButton("button1", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }); AlertDialog dialog=builder.create(); dialog.show();
2. 原始碼解析
public class AlertDialog extends AppCompatDialog implements DialogInterface {
public static class Builder { private final AlertController.AlertParams P; private final int mTheme; 1,//建構函式,使用預設的主題 public Builder(@NonNull Context context) { this(context, resolveDialogTheme(context, 0)); } //建構函式,使用明確的主題 public Builder(@NonNull Context context, @StyleRes int themeResId) { P = new AlertController.AlertParams(new ContextThemeWrapper( context, resolveDialogTheme(context, themeResId))); mTheme = themeResId; } 2,設定各種引數 public Builder setTitle(@Nullable CharSequence title) { P.mTitle = title; return this; } public Builder setMessage(@Nullable CharSequence message) { P.mMessage = message; return this; } public Builder setIcon(@Nullable Drawable icon) { P.mIcon = icon; return this; } 3,構建AlertDialog,並且將引數傳遞給AlertDialog public AlertDialog create() { 4,構建AlertDialog final AlertDialog dialog = new AlertDialog(P.mContext, mTheme); 5,將p的引數應用到dialog的Alert物件中 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; } // P.apply(dialog.mAlert); 將p的引數應用到dialog的Alert物件中 class AlertController { 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)); } } if (mMessage != null) { dialog.setMessage(mMessage); } if (mPositiveButtonText != null) { dialog.setButton(DialogInterface.BUTTON_POSITIVE, mPositiveButtonText, mPositiveButtonListener, null); } if (mNegativeButtonText != null) { dialog.setButton(DialogInterface.BUTTON_NEGATIVE, mNegativeButtonText, mNegativeButtonListener, null); } if (mNeutralButtonText != null) { dialog.setButton(DialogInterface.BUTTON_NEUTRAL, mNeutralButtonText, mNeutralButtonListener, null); } if ((mItems != null) || (mCursor != null) || (mAdapter != null)) { createListView(dialog); } if (mView != null) { if (mViewSpacingSpecified) { dialog.setView(mView, mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight, mViewSpacingBottom); } else { dialog.setView(mView); } } else if (mViewLayoutResId != 0) { dialog.setView(mViewLayoutResId); } } } 6,展示AlertDialog.show() //AlertDialog的show()方法 public AlertDialog show() { final AlertDialog dialog = create(); dialog.show(); return dialog; } //Dialog的show()方法 public class Dialog implements DialogInterface, Window.Callback, KeyEvent.Callback, OnCreateContextMenuListener, Window.OnWindowDismissedCallback { 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; } //1,呼叫AlertDialog的OnCreate() if (!mCreated) { 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); } //2,呼叫AlertDialog的OnStart() onStart(); //3,將AlertDialog的DecorView新增到windowManage mDecor = mWindow.getDecorView(); //4,設定佈局引數 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; } //5,將AlertDialog的DecorView新增到windowManage mWindowManager.addView(mDecor, l); mShowing = true; } } 7,解析onCreate() //Dialog中的onCreate()是一個空的方法,因此呼叫子類AlertDialog中的OnCreate() @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAlert.installContent(); } class AlertController { //將佈局AlertDialog載入進來 public AlertController(Context context, AppCompatDialog di, Window window) { mContext = context; mDialog = di; mWindow = window; mHandler = new ButtonHandler(di);
final TypedArray a = context.obtainStyledAttributes(null, R.styleable.AlertDialog, R.attr.alertDialogStyle, 0);
mAlertDialogLayout = a.getResourceId(R.styleable.AlertDialog_android_layout, 0); mButtonPanelSideLayout = a.getResourceId(R.styleable.AlertDialog_buttonPanelSideLayout, 0);
mListLayout = a.getResourceId(R.styleable.AlertDialog_listLayout, 0); mMultiChoiceItemLayout = a.getResourceId(R.styleable.AlertDialog_multiChoiceItemLayout, 0); mSingleChoiceItemLayout = a .getResourceId(R.styleable.AlertDialog_singleChoiceItemLayout, 0); mListItemLayout = a.getResourceId(R.styleable.AlertDialog_listItemLayout, 0); mShowTitle = a.getBoolean(R.styleable.AlertDialog_showTitle, true);
a.recycle();
/* We use a custom title so never request a window title */ di.supportRequestWindowFeature(Window.FEATURE_NO_TITLE); } public void installContent() { //建構函式中載入佈局 final int contentView = selectContentView(); mDialog.setContentView(contentView); //顯示佈局 setupView(); } } }