Android开发之Buidler模式初探结合AlertDialog.Builder讲解

时间:2022-10-01 21:37:15
      什么是Buidler模式呢?就是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示.Builder模式是一步一步创建一个复杂的对象,它允许用户可以只通过指定复杂对象的类型和内容就可以构建它们.

       那么要为何使用Buidler呢?

       是为了将构建复杂对象的过程和它的部件分开因为一个复杂的对象,不但有很多大量组成部分,如AlertDialog对话框,有很多组成部件,比如Tittle,Message,icon,PositiveButton等等,但远不止这些,如何将这些部件装配成一个AlertDialog对话框呢,这个装配程可能也是一个很复杂的步骤,Builder模式就是为了将部件和组装过程分开。通俗点说,就是我先分开生产好各个组件,然后交由另一个类去组装这些组件。

       如何使用?

       我们来看一下Android内部关于AlertDialog.Builder的源代码便可以知晓。

public class AlertDialog extends Dialog implements DialogInterface {      // Controller, 接受Builder成员变量P中的各个参数  
private AlertController mAlert;

// 构造函数
protected AlertDialog(Context context, int theme) {
this(context, theme, true);
}

// 4 : 构造AlertDialog
AlertDialog(Context context, int theme, boolean createContextWrapper) {
super(context, resolveDialogTheme(context, theme), createContextWrapper);
mWindow.alwaysReadCloseOnTouchAttr();
mAlert = new AlertController(getContext(), this, getWindow());
}

// 实际上调用的是mAlert的setTitle方法
@Override
public void setTitle(CharSequence title) {
super.setTitle(title);
mAlert.setTitle(title);
}

// 实际上调用的是mAlert的setCustomTitle方法
public void setCustomTitle(View customTitleView) {
mAlert.setCustomTitle(customTitleView);
}

public void setMessage(CharSequence message) {
mAlert.setMessage(message);
}

// AlertDialog其他的代码省略

// ************ Builder为AlertDialog的内部类 *******************
public static class Builder {
// 1 :该类用来存储AlertDialog的各个参数, 例如title, message, icon等.
private final AlertController.AlertParams P;


/**
* Constructor using a context for this builder and the {@link AlertDialog} it creates.
*/
public Builder(Context context) {
this(context, resolveDialogTheme(context, 0));
}


public Builder(Context context, int theme) {
P = new AlertController.AlertParams(new ContextThemeWrapper(
context, resolveDialogTheme(context, theme)));
mTheme = theme;
}



// 2:设置各种参数到P
public Builder setTitle(CharSequence title) {
P.mTitle = title;
return this;
}


public Builder setMessage(CharSequence message) {
P.mMessage = message;
return this;
}

public Builder setIcon(int iconId) {
P.mIconId = iconId;
return this;
}

public Builder setPositiveButton(CharSequence text, final OnClickListener listener) {
P.mPositiveButtonText = text;
P.mPositiveButtonListener = listener;
return this;
}


public Builder setView(View view) {
P.mView = view;
P.mViewSpacingSpecified = false;
return this;
}

// 3 : 构建AlertDialog, 传递参数
public AlertDialog create() {
// 调用new AlertDialog构造对象, 并且将参数传递个体AlertDialog
final AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);
// 5 : 将P中的参数应用的dialog中的mAlert对象中
//这一步是核心方法我们等下看源码继续讲
P.apply(dialog.mAlert);
dialog.setCancelable(P.mCancelable);
if (P.mCancelable) {
dialog.setCanceledOnTouchOutside(true);
}
dialog.setOnCancelListener(P.mOnCancelListener);
if (P.mOnKeyListener != null) {
dialog.setOnKeyListener(P.mOnKeyListener);
}
return dialog;
}
public AlertDialog show() {
//6:显示dialog
AlertDialog dialog = create();
dialog.show();
return dialog;
}
}

}
     从上面的源码中我们可以看到,对话框的构建是通过Builder来设置AlertDialog中的title, message, button等参数, 这些参数都存储在类型为AlertController.AlertParams的成员变量P中,AlertController.AlertParams中包含了与之对应的成员变量。在调用Builder类的create函数时才创建AlertDialog, 并且将Builder成员变量P中保存的参数应用到AlertDialog的mAlert对象中,最后调用dialog.show方法显示对话框。

      现在我们再来看看即P.apply(dialog.mAlert)代码段。我们看看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));          }      }      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 (mForceInverseBackground) {          dialog.setInverseBackgroundForced(true);      }      // For a list, the client can either supply an array of items or an      // adapter or a cursor      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);          }      }  }
       实际上就是把P中的参数挨个的设置到AlertController中, 也就是AlertDialog中的mAlert对象。从AlertDialog的各个setter方法中我们也可以看到,实际上也都是调用了mAlert对应的setter方法。
       综上看完上面源码之后我们就可以发现,怪不得我们平时调用对话框的时候可以直接使用,AlertDialog dialog = new AlertDialog(P.mContext, mTheme, false);不用Alert.Builder方法创建也可以,因为其本质是一样的,Builder只是把组件的生产过程化成一步步实行而已。

       这样做有什么实际作用呢?

      在Java实际使用中,我们经常用到"池"(Pool)的概念,当资源提供者无法提供足够的资源,并且这些资源需要被很多用户反复共享时,就需要使用池。"池"实际是一段内存,当池中有一些复杂的资源的"断肢"(比如数据库的连接池,也许有时一个连接会中断),如果循环再利用这些"断肢",将提高内存使用效率,提高池的性能,而在这里AlertDialog.builder就是这个池,修改Builder模式中p.apply(组装)类使之能诊断"断肢"断在哪个部件上,再修复这个部件.