AlertDialog源码分析

在Android源码中,最常用到的Builder模式的就是AlertDialog.Builder.

public class AlertDialog extends AppCompatDialog implements DialogInterface {

    final AlertController mAlert;   //用来接收Builder成员变量P中的各个参数
    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);
  //实际上是mAlert的setTitle方法
        mAlert.setTitle(title);
    }
 Builder是AlertDialog 的内部类
public static class Builder {
        private final AlertController.AlertParams P;
        private final int mTheme;

     
        public Builder(@NonNull Context context) {
            this(context, resolveDialogTheme(context, 0));
        }


//设置各种参数
        public Builder setView(View view) {
            P.mView = view;
            P.mViewLayoutResId = 0;
            P.mViewSpacingSpecified = false;
            return this;
        }
//构建AlertDialog,传递参数
        public AlertDialog create() {
       
            final AlertDialog dialog = new AlertDialog(P.mContext, mTheme);
//将p中的参数应用到dialog的mAlert对象中
            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设置AlertDialog中title、message、button等参数,这些参数都存储在AlertController.AlertParams P中,其中包含了与AlertDialog视图中对应的成员变量
看一下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函数中,只是将AlertParams 参数设置到AlertController中,例如,将标题设置到Dialog对应的标题视图中,需要我们调用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) {
//来调用AlertDialog的oncreate()函数
            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);
        }
//调用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()这个方法


 void dispatchOnCreate(Bundle savedInstanceState) {
        if (!mCreated) {
            onCreate(savedInstanceState);//调用Dialog的oncreate,空方法,   AlertDialog继承Dialog,其自身实现
            mCreated = true;
        }
    }
AlertDialog的oncreate()方法
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mAlert.installContent();
    }
跳转进去,查看其方法
public void installContent() {
        final int contentView = selectContentView();
        mDialog.setContentView(contentView);
        setupView();
    }
调用setContentView和Activity的一样,这里设置AlertDialog的内容布局,这个内容布局就是mAlertDialogLayout字段的值,这个值在AlertController的构造函数中进行了初始化。

最后就是setupView()方法了,初始化AlertDialog布局中各个部分,Dialog视图部分设置完毕。 当用户调用show()方法时,WindowManager会将Window的DecorView(mAlertDialogLayout的视图), mWindowManager.addView(mDecor, l);添加到用户窗口上。
至此,Dialog就出现在用户的视野中了。。。。。

Builder模式

你可能感兴趣的:(AlertDialog源码分析)