一.构建者模式

  • 不熟悉构建者设计模式的童靴可以参考下面文章:
    • 菜鸟教程-建造者模式
    • Java设计模式之《构建者模式》及应用场景

      二.源码分析

      2.1.在界面中构建AlertDialog

      1. //构建AlertDialog,sdk版本:28 android.app包下
      2. AlertDialog.Builder builder = new AlertDialog.Builder(this);
      3. builder.setIcon(R.drawable.ic_launcher_background)
      4. .setTitle("头部")
      5. .setMessage("内容")
      6. .setPositiveButton("确定", new DialogInterface.OnClickListener() {
      7. @Override
      8. public void onClick(DialogInterface dialog, int which) {
      9. Toast.makeText(MainActivity.this,"点击确定按钮",Toast.LENGTH_SHORT).show();
      10. }
      11. })
      12. .setNegativeButton("取消", new DialogInterface.OnClickListener() {
      13. @Override
      14. public void onClick(DialogInterface dialog, int which) {
      15. Toast.makeText(MainActivity.this,"点击取消按钮",Toast.LENGTH_SHORT).show();
      16. }
      17. })
      18. .create()
      19. .show();

2.2.builder创建—->setXxx—->create—->show

  1. //AlertDialog类
  2. public class AlertDialog extends Dialog implements DialogInterface {
  3. private AlertController mAlert;
  4. //省略...
  5. //注意:根据修饰符可知,不能直接new对象
  6. protected AlertDialog(Context context, @StyleRes int themeResId) {
  7. this(context, themeResId, true);
  8. }
  9. //构造函数
  10. AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
  11. super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,
  12. createContextThemeWrapper);
  13. mWindow.alwaysReadCloseOnTouchAttr();
  14. mAlert = AlertController.create(getContext(), this, getWindow());
  15. }
  16. //省略...
  17. // ************ 注意:Builder为AlertDialog的内部类 *******************
  18. public static class Builder对象,调用构造函数 {
  19. //问题: final修饰了,还是再被赋值 怎么解释呢?
  20. private final AlertController.AlertParams P;
  21. //1.创建Builder对象,调用构造函数
  22. public Builder(Context context) {
  23. this(context, resolveDialogTheme(context, ResourceId.ID_NULL));
  24. }
  25. public Builder(Context context, int themeResId) {
  26. P = new AlertController.AlertParams(new ContextThemeWrapper(
  27. context, resolveDialogTheme(context, themeResId)));
  28. }
  29. //省略...
  30. //2.调用Builder对象中的setXxx方法
  31. //设置P中的mTitle属性
  32. public Builder setTitle(CharSequence title) {
  33. P.mTitle = title;
  34. return this;
  35. }
  36. //省略setXxx...
  37. //3.构建AlertDialog, 传递参数
  38. public AlertDialog create() {
  39. // Context has already been wrapped with the appropriate theme.
  40. //4.调用AlertDialog构造函数
  41. final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);
  42. //5.调用AlertController类中AlertParams对象的apply方法
  43. P.apply(dialog.mAlert);
  44. dialog.setCancelable(P.mCancelable);
  45. if (P.mCancelable) {
  46. dialog.setCanceledOnTouchOutside(true);
  47. }
  48. dialog.setOnCancelListener(P.mOnCancelListener);
  49. dialog.setOnDismissListener(P.mOnDismissListener);
  50. if (P.mOnKeyListener != null) {
  51. dialog.setOnKeyListener(P.mOnKeyListener);
  52. }
  53. return dialog;
  54. }
  55. //省略...
  56. }
  57. //省略...
  58. }

2.3.AlertDialog的构造方法和内部类Builder

  1. public class AlertDialog extends Dialog implements DialogInterface {
  2. //位置二:包含AlertController对象;
  3. private AlertController mAlert;
  4. //...
  5. //位置一:构造方法被protected修饰,故不能直接new(而是通过内部类Builder来构建,后面分析);
  6. protected AlertDialog(Context context) {
  7. this(context, 0);
  8. }
  9. protected AlertDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
  10. this(context, 0);
  11. setCancelable(cancelable);
  12. setOnCancelListener(cancelListener);
  13. }
  14. protected AlertDialog(Context context, @StyleRes int themeResId) {
  15. this(context, themeResId, true);
  16. }
  17. //构造方法,默认的修饰符,只能在同一个包中访问
  18. AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
  19. super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,
  20. createContextThemeWrapper);
  21. mWindow.alwaysReadCloseOnTouchAttr();
  22. mAlert = AlertController.create(getContext(), this, getWindow());
  23. }
  24. //...
  25. //位置三:内部类Builder
  26. public static class Builder {
  27. //位置四:包含AlertController的AlertParams对象
  28. private final AlertController.AlertParams P;
  29. public Builder(Context context) {
  30. this(context, resolveDialogTheme(context, ResourceId.ID_NULL));
  31. }
  32. public Builder(Context context, int themeResId) {
  33. P = new AlertController.AlertParams(new ContextThemeWrapper(
  34. context, resolveDialogTheme(context, themeResId)));
  35. }
  36. //...
  37. }

2.4.AlertController

  1. public class AlertController {
  2. //省略...
  3. public static class AlertParams {
  4. //省略...
  5. public AlertParams(Context context) {
  6. mContext = context;
  7. mCancelable = true;
  8. mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  9. }
  10. //省略...
  11. //分析二
  12. public void apply(AlertController dialog) {
  13. //给非空的属性赋值
  14. //调用setView方法
  15. }
  16. }
  17. //省略...
  18. }

2.5.AlertController的create方法

  1. public class AlertDialog extends Dialog implements DialogInterface {
  2. //...
  3. /**
  4. * Creates an {@link AlertDialog} with the arguments supplied to this
  5. * builder.
  6. * <p>
  7. * Calling this method does not display the dialog. If no additional
  8. * processing is needed, {@link #show()} may be called instead to both
  9. * create and display the dialog.
  10. */
  11. public AlertDialog create() {
  12. // Context has already been wrapped with the appropriate theme.
  13. //创建dialog,查看构造方法 ---> 分析一
  14. final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);
  15. //接着调用AlertController.AlertParams P的apply方法(相当于组装步骤) ---> 分析二
  16. P.apply(dialog.mAlert);
  17. dialog.setCancelable(P.mCancelable);
  18. if (P.mCancelable) {
  19. dialog.setCanceledOnTouchOutside(true);
  20. }
  21. dialog.setOnCancelListener(P.mOnCancelListener);
  22. dialog.setOnDismissListener(P.mOnDismissListener);
  23. if (P.mOnKeyListener != null) {
  24. dialog.setOnKeyListener(P.mOnKeyListener);
  25. }
  26. return dialog;
  27. }
  28. //...
  29. AlertDialog(Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
  30. super(context, createContextThemeWrapper ? resolveDialogTheme(context, themeResId) : 0,
  31. createContextThemeWrapper);
  32. mWindow.alwaysReadCloseOnTouchAttr();
  33. //分析一 : AlertDialog中包含mAlert对象,传入参数:上下文,DialogInterface,Window
  34. mAlert = AlertController.create(getContext(), this, getWindow());
  35. }
  36. }

2.6.包含关系展示

dialog源码分析.png

  • AlertDialog —> 包含Builder类;
    • AlertDialog构造方法中初始化AlertController对象;
    • Builder类中初始化AlertParams对象;
  • AlertController —> 包含AlertParams类;
  • Builder同时扮演了抽象的builder、具体的ConcreteBuilder、指挥者Director(直接采用链式调用,省去了Director)的角色,简化了Builder模式的设计;
    • AlertDialog(电脑对象)
    • AlertDialog.Builder 规范一系列的组装过程
    • AlertController 具体的构建器
    • AlertController.AlertParams 存放参数,一部分设置参数的功能
  • show方法在Dialog中查看.

三.打造dialog

  • 根据2.6图中的包含关系可知,我们需要定义两个类,AlertDialog和AlertController,其中AlertDialog类中会定义一个内部类Builder,AlertController会定义一个内部类AlertParams.
  • 生成的AlertDialog对象需要设置的属性,都放在AlertController内部类AlertParams中作为内部类变量,AlertParams中的变量通过Builder中设定setXxx方法来设置.
  • 属性都定义好之后,通过builder中的方法来生成AlertDialog对象.
  • 额外创建一个工具类,打造的对话框一共有三个类.

四.源码

github地址