Android 源码的建造者模式

Android 源码的建造者模式

建造者模式可以将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

以 android 29 的代码为例,介绍 AlertDialog.Builder 和 ActivityStarter.Request。

AlertDialog.Builder

Android 对话框 AlertDialog 的构建过程是一个典型的建造者模式,它的构造依赖内部类 Builder。

    public static class Builder {
        @UnsupportedAppUsage
        private final AlertController.AlertParams P;
        ...
        public Builder(Context context) {
            this(context, resolveDialogTheme(context, Resources.ID_NULL));
        }
        ...
        public Builder setTitle(CharSequence title) {
            P.mTitle = title;
            return this;
        }
        ...
        public AlertDialog create() {
            // Context has already been wrapped with the appropriate theme.
            final AlertDialog dialog = new AlertDialog(P.mContext, 0, false);
            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;
        }
...
        public AlertDialog show() {
            final AlertDialog dialog = create();
            dialog.show();
            return dialog;
        }
    }

可以看出调用 setTitle 会把 title 赋值给 AlertController.AlertParams P,在 create 的时候会使用 P.apply 传递参数到 dialog 的 mAlert 中,最后返回构建好的 dialog。

        public void apply(AlertController dialog) {
            if (mCustomTitleView != null) {
                dialog.setCustomTitle(mCustomTitleView);
            } else {
                if (mTitle != null) {
                    dialog.setTitle(mTitle);
                }
                if (mIcon != null) {
                    dialog.setIcon(mIcon);
                }
                ...
        }

AlertParams 的 apply 方法会把参数传递给 AlertController。

Dialog 的 show 方法如下:

    public void show() {
        ...
        if (!mCreated) {
            dispatchOnCreate(null);
        }
        ...
        onStart();
        mDecor = mWindow.getDecorView();
        ...
        mWindowManager.addView(mDecor, l);
        ...
        mShowing = true;

        sendShowMessage();
    }

可以看出 show 方法回调了 create、start 的生命周期方法,最后通过 mWindowManager.addView 显示出来。

ActivityStarter.Request

查看 ActivityTaskManagerService 的 startActivityAsUser 方法。

    int startActivityAsUser(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
            boolean validateIncomingUser) {
        ...
        return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
                .setCaller(caller)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();

    }

startActivityAsUser 构造了 ActivityStarter 并调用它的 execute 启动 Activity。

    ActivityStarter setCaller(IApplicationThread caller) {
        mRequest.caller = caller;
        return this;
    }

ActivityStarter 的 setCaller 方法把 caller 赋值给 mRequest,然后返回它自己。

    ActivityStarter setMayWait(int userId) {
        mRequest.mayWait = true;
        mRequest.userId = userId;

        return this;
    }

ActivityStarter 的 setMayWait 方法把 mayWait 赋值为 true,也就是说要等待启动 Activity 的结果,然后传递 userId。

ActivityStarter 的 execute 方法如下:

int execute() {
        try {
            // TODO(b/64750076): Look into passing request directly to these methods to allow
            // for transactional diffs and preprocessing.
            if (mRequest.mayWait) {
                return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                        mRequest.callingPackage, mRequest.realCallingPid, mRequest.realCallingUid,
                        mRequest.intent, mRequest.resolvedType,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                        mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                        mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                        mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup,
                        mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
            } else {
                return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                        mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                        mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                        mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                        mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                        mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                        mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                        mRequest.outActivity, mRequest.inTask, mRequest.reason,
                        mRequest.allowPendingRemoteAnimationRegistryLookup,
                        mRequest.originatingPendingIntent, mRequest.allowBackgroundActivityStart);
            }
        } finally {
            onExecutionComplete();
        }
    }

可以看出 execute 方法根据 mRequest.mayWait 值,判断是执行 startActivityMayWait 还是 startActivity,最后把 mRequest 的每个属性传递给了这两个方法,完成 Activity 的启动。

发布了105 篇原创文章 · 获赞 2 · 访问量 3769

猜你喜欢

转载自blog.csdn.net/caoshen2014/article/details/102713744
今日推荐