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