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 的启动。

更多相关文章

  1. 常用的控件使用方法(TextView及其常用属性)
  2. Android(安卓)- Compass(罗盘) 详解
  3. 底部导航栏:利用viewpager实现Android底部标题栏
  4. android手机连接到ubuntu方法
  5. Android事件总线(二)EventBus3.0源码解析
  6. 读书笔记——《Android(安卓)开发艺术探索》Activity工作过程阅
  7. Android进阶(三)ButterKnife源码解析
  8. 【Android】: 部分注意事项
  9. ListView去掉默认点击效果

随机推荐

  1. TCPIP卷一(11):EIGRP的汇总、stub、leak-map
  2. 价值
  3. TCPIP卷一(9):EIGRP的数据包格式、TLV、 三
  4. 容器?
  5. TCPIP卷一(7):Routing Information Protocol
  6. 9月的风,我们重新认识一下
  7. 如何做好一件事
  8. TCPIP卷一(10):EIGRP的DUAL算法和SIA解决方
  9. TCPIP卷一(2):二层封装之–PPP与FR
  10. TCPIP卷一(6):距离矢量与链路状态 路由选择