本文主要记录在Activity中View与Window相互作用关系,以及如何管理Window的展示、删除和更新。
创建Window
ActivityThread收到launchActivity消息后,会调用performLaunchActivity方法开始创建Activity相关流程
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {//***准备工作//创建ContextImpl对象ContextImpl appContext = createBaseContextForActivity(r);Activity activity = null;try {java.lang.ClassLoader cl = appContext.getClassLoader();/反射创建Activity对象activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);//****try {//如果当前进程application为null,则会创建application并调用attachBaseContext,onCreate等方法Application app = r.packageInfo.makeApplication(false, mInstrumentation);if (activity != null) {Window window = null;if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {window = r.mPendingRemoveWindow;r.mPendingRemoveWindow = null;r.mPendingRemoveWindowManager = null;}appContext.setOuterContext(activity);//调用activity的attach方法,此时window参数是nullactivity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config,r.referrer, r.voiceInteractor, window, r.configCallback,r.assistToken, r.shareableActivityToken);if (customIntent != null) {activity.mIntent = customIntent;}//回调onCreate方法,在该方法中会将业务View加载到decorview中if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}//****return activity;}
创建activity后,回调activity的attach方法,window就在这个方法中创建
final void attach(Context context, ActivityThread aThread,Instrumentation instr, IBinder token, int ident,Application application, Intent intent, ActivityInfo info,CharSequence title, Activity parent, String id,NonConfigurationInstances lastNonConfigurationInstances,Configuration config, String referrer, IVoiceInteractor voiceInteractor,Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken,IBinder shareableActivityToken) {//调用activity的attachBaseContext方法attachBaseContext(context);mFragments.attachHost(null /*parent*/);//这里创建PhoneWindow对象,该对象就是window的实现类mWindow = new PhoneWindow(this, window, activityConfigCallback);mWindow.setWindowControllerCallback(mWindowControllerCallback);//activity本身就是window的callback实现者,这里设置给window来接收window相关的事件mWindow.setCallback(this);mWindow.setOnWindowDismissedCallback(this);mWindow.getLayoutInflater().setPrivateFactory(this);if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {mWindow.setSoftInputMode(info.softInputMode);}if (info.uiOptions != 0) {mWindow.setUiOptions(info.uiOptions);}//****省略一些赋值操作//获取WindowManager,实际是WindowManagerGlobal对象,mWindowManager = mWindow.getWindowManager();//**** }
上述可知,activity的window对象是在attch方法中创建,其是PhoneWindow的实例。
添加View
添加View到window上主要在ActivityThread的handleResumeActivity方法中
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,boolean isForward, String reason) {//分发OnResume方法if (!performResumeActivity(r, finalStateRequest, reason)) {return;}final Activity a = r.activity;boolean willBeVisible = !a.mStartedActivity;if (!willBeVisible) {willBeVisible = ActivityClient.getInstance().willActivityBeVisible(a.getActivityToken());}if (r.window == null && !a.mFinished && willBeVisible) {r.window = r.activity.getWindow();View decor = r.window.getDecorView();decor.setVisibility(View.INVISIBLE);ViewManager wm = a.getWindowManager();//*****if (a.mVisibleFromClient) {if (!a.mWindowAdded) {a.mWindowAdded = true;//调用WindowManager的addView方法wm.addView(decor, l);} else {//*****}}//**r.activity.mVisibleFromServer = true;mNumVisibleActivities++;if (r.activity.mVisibleFromClient) {//调用Activity的makeVisible方法展示内容r.activity.makeVisible();}}
上述代码可以发现,在onresume的流程中会调用WindowManagerglobal的addView方法添加View
//WindowManagerGlobal成员变量, 每个窗口的根View,数量和Window 1:1private final ArrayList<View> mViews = new ArrayList<View>();//WindowManagerGlobal成员变量, 每个窗口的根View和window的连接器,数量和Window 1:1private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();//WindowManagerGlobal成员变量, 每个窗口的参数,数量和Window 1:1private final ArrayList<WindowManager.LayoutParams> mParams =new ArrayList<WindowManager.LayoutParams>();//WindowManagerGlobal成员变量, 当前正在移除的Viewprivate final ArraySet<View> mDyingViews = new ArraySet<View>();public void addView(View view, ViewGroup.LayoutParams params,Display display, Window parentWindow, int userId) {//参数校验ViewRootImpl root;View panelParentView = null;synchronized (mLock) {//创建ViewRootImpl对象root = new ViewRootImpl(view.getContext(), display);view.setLayoutParams(wparams);///将view,root,和窗口参数添加到集合中,标记着一个Window被记录了mViews.add(view);mRoots.add(root);mParams.add(wparams);try {//调用root的setView方法root.setView(view, wparams, panelParentView, userId);} catch (RuntimeException e) {}}}
展示View
接下来分析setView相关的流程
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,int userId) {synchronized (this) {if (mView == null) {mView = view;//绑定view和AttachInfomAttachInfo.mRootView = view;mAdded = true;int res; /* = WindowManagerImpl.ADD_OKAY; *///请求测量/布局/绘制requestLayout();try {//在WMS中创建一个与Window相关的对象,WMS管理所有的Window的层级、位置、大小res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,getHostVisibility(), mDisplay.getDisplayId(), userId,mInsetsController.getRequestedVisibility(), inputChannel, mTempInsets,mTempControls);} //***setFrame(mTmpFrames.frame);//绑定View和ViewRootImplview.assignParent(this);}}}
由上述可以知道,setView方法主要做两件大事:1.将View和ViewRootImpl绑定后开启View绘制请求(requestLayout),并通过IPC请求WMS创建Surface,2.通过WindowSession进行IPC调用给WMS中创建一个与Window相关的对象,然后WMS管理所有的Window的层级、位置、大小。应用端在WMS分配Surface的绘制完成,SurfaceFlinger会把这些Surface图像数据按WMS中的层级、位置、大小等进行合成,最终写屏幕的缓冲区显示出来。详细的流程可以查看performTraversals方法
private void performTraversals() {//通过IPC创建&申请SurfacerelayoutResult = relayoutWindow(params, viewVisibility, insetsPending);performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);performLayout(lp, mWidth, mHeight);performDraw();}