前言
这几天开始看Window相关的内容,会把相关的东西记录在这儿,以备以后查阅。内容及内容结构会逐步迭代完善。
1. Window是抽象基类,只有PhoneWindow一个抽象基类
android.jar中的Window声明:
public abstract class Window {
...
}
Window的类结构示意图:
Window类声明说明确实是抽象基类,Window结构示意图说明确实只有PhoneWindow实现类。
2. 官方文档中对Window的介绍
Abstract base class for a top-level window look and behavior policy.
An instance of this class should be used as the top-level view added to the window manager.
It provides standard UI policies such as a background, title area, default key processing, etc.
翻译过来的意思是,
Window,一个负责管理窗口显示、定义行为交互策略的顶层抽象基类;
Window的实例对象应该被当做最顶层的View添加到WindowManager中;
Window,提供了一套诸如背景设置、title区域设置、默认输入事件处理等标准的UI显示及行为处理策略
3. WindowManager
源码中的WindowManager中的声明:
public interface WindowManager extends ViewManager {
...
}
可见,WindowManager是一个接口,并继承ViewManager接口。ViewManager中声明就很简单了:
public interface ViewManager
{
//添加view
public void addView(View view, ViewGroup.LayoutParams params);
//更新View的布局
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
//移除View
public void removeView(View view);
}
主要的操作是:添加View、更新View、移除View。下面看一下WindowManager的类继承结构:
与Window的类继承结构类似,WindowManager也只有一个实现类,WindowManagerImpl。查看WindowManagerImpl的构造方法被调用的地方,发现在WindowManagerImpl类之外,只有一个地方创建了WindowManagerImpl对象:
package android.app;
final class SystemServiceRegistry {
...
static {
...//此处省略大量registerService方法调用
registerService(Context.WINDOW_SERVICE, WindowManager.class,
new CachedServiceFetcher() {
@Override
public WindowManager createService(ContextImpl ctx) {
return new WindowManagerImpl(ctx);
}});
...//此处省略大量registerService方法调用
}
...
}
这也就是注册系统服务的地方了,此处注册的是WINDOW_SERVICE,获取该Window服务,可通过Context.getSystemService(Context.WINDOW_SERVICE)。SystemServiceRegistry类中的该static代码块中有大量注册服务(registerService)代码,再结合该类中的其他方法诸如createServiceCache、getSystemService,基本可以推测出SystemServiceRegistry此类就是用来做系统服务的注册和获取的。
既然说到了这里,那就继续探究一下SystemServiceRegistry的静态代码块什么时候会被调用呢?先看一下SystemServiceRegistry
被调用的地方,如下图:
如图所示,只有一个叫做ContextImpl的类中使用了SystemServiceRegistry。看到ContextImp就能想到很多了,比如这张清晰明了的Context继承关系示意图:
再比如说,ContextWrapper只是提供方法,这些方法的具体实现其实都是在ContextImpl中。再来看一下ContextImpl调用SystemServiceRegistry的那几个方法,一个createXXX,两个getXXX。看一下createXXX方法就可以了:
class ContextImpl extends Context {
...
// The system service cache for the system services that are cached per-ContextImpl.
final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();
...
}
上述代码非常清晰地显示了SystemServiceRegistry.createXXX()方法在创建ContextImpl对象给其成员变量mServiceCache初始化时就会被调用。而另外两个getXXX方法,都是在ContextImpl的具体方法中调用的,当然在初始化成员变量的SystemServiceRegistry.createXXX()较另外两个getXXX方法先被执行,执行时也就是SystemServiceRegistry类被导入到内存时。也就是说在ContextImpl对象初始化时,SystemServiceRegistry类会被导入内存,进而执行SystemServiceRegistry的static代码块。那么最早的ContextImpl对象是在什么时候创建的呢?
我们知道Application也是一种Context,Context的衍生子类中有Application。查看ActivityThread中创建application一步一步走下去会看到下面这段代码,证实了创建Application对象时也会创建ContextImp对象:
package android.app;
public final class LoadedApk {
...
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
...
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
...
}
...
}
所以,基本可以推测,SystemServiceRegistry的静态方法最先执行是在app启动创建Application对象的时候。
废话有点儿多,言归正传,继续说Window。
4. WindowManagerService
WindowManagerService是framework层的窗口管理服务,管理的是系统中全部Window。运行在一个非app进程的进程内(基本可以确定是SystemServer进程内),是用于接收来自于app进程window操作信息的binder线程。一次可管理多个Window。
查资料时查到了对窗口本质的一段描述,里面也涉及到了WindowManagerService,所以就写在这个小标题下面了:Window的本质是一块显示区域,在android中就是可绘制的画布:surface,当surface显示到屏幕上之后就是我们看到的Window了。WindowManagerService添加Window,其实就是在为app分配Surface,WindowManagerService还能够管理各个Window,使其有序地排列在屏幕上。
什么是android的显示系统呢?上面这篇资料也给出了解释并给了图,个人认为非常清晰明了:
上图中非常清晰地介绍了android显示系统三个层次各自的职责范围。另外,app进程中的Window也属于系统中的窗口,也需要WindowManagerService(管理系统中所有的Window)去管理,这就需要app进程与WindowManagerService进行跨进程通信了。还有,这里第一次看到SurfaceFlinger,原来是它将Surface显示到屏幕上的,这就是android系统的surface机制。
下面是WindowManagerService在android.jar中的声明:
package com.android.server.wm;
/** {@hide} */
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
...
}
因为@hide
的存在,所以这个类一般在android.jar中是不可见的,可以通过替换jar包显示出来。另外看到Stub应该可以联想出来一些Binder相关的内容:
public interface IMyAidlInterface extends android.os.IInterface {
public static abstract class Stub extends android.os.Binder implements IMyAidlInterface {
...
public static IMyAidlInterface asInterface(android.os.IBinder obj) {
...
}
...
@Override
public android.os.IBinder asBinder() {
return this;
}
...
@Override
public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
...
}
...
private static class Proxy implements IMyAidlInterface {
Proxy(android.os.IBinder remote) {
...
}
...
@Override
public android.os.IBinder asBinder() {
return mRemote;
}
...
//在某个方法中调用mRemote.transact方法
...
}
...
}
}
上面这段代码基本就是Binder通信代码部分的基本结构了:IMyAidlInterface为接口并继承IInterface接口,Stub为IMyAidlInterface的静态抽象内部类并继承Binder、实现IMyAidlInterface,Proxy为Stub的静态内部类并实现IMyAidlInterface。另外,Stub中onTransact方法用来接收跨进程传来的信息,Proxy中调用transact用来向别的进程传递信息。
那下面看一下,WindowManagerService的声明
package com.android.server.wm;
public class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
...
}
IWindowManager的声明及简单结构
package android.view;
public interface IWindowManager extends android.os.IInterface {
static abstract class Stub extends android.os.Binder implements android.view.IWindowManager {
...
public android.os.IBinder asBinder() {
...
}
...
public boolean onTransact(int i, android.os.Parcel parcel, android.os.Parcel parcel1, int i1) throws android.os.RemoteException {
...
}
...
private static class Proxy implements android.view.IWindowManager {
...
Proxy(android.os.IBinder iBinder) {...}
...
public android.os.IBinder asBinder() { ... }
...
}
}
}
有没有发现IWindowManager代码结构与IMyAidlInterface代码结构十分相似?只不过WindowManagerService继承了Stub,单独写成了一个独立的类。对的,它们本来就都是Binder机制,当然要相似。我想说的是,我们懂得Binder代码基本结构(就是,IMyAidlInterface的代码结构)各个部分的功能,那也就能够类比出WindowManagerService机制中哪些方法是用来接收信息,哪些方法是用来组装pacel发送信息的,哪些方法是用来判断当前binder是否为本进程对象的。
WindowManagerService、ActivityManagerService、ApplicationThread等通信机制,其实都是binder机制,代码层次结构、继承关系都符合binder机制的基本代码结构(IMyAidlInterface的代码结构)。通过类比的方式,理解起这些通信机制就容易很多。
5. window的分类
Window分为三类:应用窗口(application window)、子窗口(sub window)、系统窗口(System Widow)。
- 应用窗口:就是一般app的窗口,Activity对一个的窗口。
- 子窗口:不能单独存在的窗口,需要依附在特定的父窗口中,比如popupWindow、菜单弹出框(Menu);
- 系统窗口:系统级别的窗口,比如说ANR时的系统异常窗口、系统状态栏、屏保窗口、toast窗口、输入法窗口、壁纸窗口等。在使用时需注意,有些系统窗口需要相关权限。
那这些窗口类型在代码中怎么设置呢?通过WindowManager.LayoutParams中type字段进行设置。先看一下,WindowManager.LayoutParams
public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
...
}
继承了ViewGroup.LayoutParams实现Parcelable,主要作用是设置Window的布局参数。看了此type的文档之后,你会发现上面所述的三种类型并不是对应三个type而是对应3个type范围。
窗口类型 | type取值范围 |
---|---|
应用窗口 | 1 ~ 99,FIRST_APPLICATION_WINDOW~LAST_APPLICATION_WINDOW |
子窗口 | 1000 ~ 1999,FIRST_SUB_WINDOW~LAST_SUB_WINDOW |
系统窗口 | 2000 ~ 2999,FIRST_SYSTEM_WINDOW~LAST_SYSTEM_WINDOW |
每一个Window都对应z-ordered,type值大的Window会覆盖type值小的Window。另外,WindowManager.LayoutParams中定义了许多type常量,想要对这些type有一个整体的了解的话,可以参看这篇文章的“Window分类”部分。
6. Activity创建过程中,Window、WindowManager所起的作用
1. Activity回调onCreate之前
Activity是怎么创建的呢?整个过程是怎样的呢?从调用Activity的startActivity开始,继而执行Instrumetation的execStartActivity,然后通过Binder机制,app进程中的ActivityThreadProxy与SystemServer进程中的ActivityManagerService进行通信告知要启动一个Activity,ActivityManagerService通过同进程的ApplicationThreadProxy与app进程中的ApplicationThread进行通信告知要启动一个Activity,ApplicationThread通过ActivityThread的mh这个Handler对象发送一个类型为“LAUNCH_ACTIVITY”消息给UI主线程,UI主线程取出消息,开始为显示一个Activity做准备。
经过上面的这些过程,之后会执行到ActivityThread的performLaunchActivity方法:
package android.app;
public final class ActivityThread {
...
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
//使用ClassLoarder反射出Activity对象
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
}
try {
//创建Application对象,里面有已创建就不再去创建的逻辑
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
//创建当前Activity的Context对象
Context appContext = createBaseContextForActivity(r, activity);
...//配置相关
//初始化Window
...//Window的一些标记
//activity的attach方法就是创建Window对象的地方
activity.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);
}
...
//设置主题
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
//回调onCreate方法
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
if (!r.activity.mFinished) {
activity.performStart();//在这里面会回调onStart方法
r.stopped = false;
}
...
}} catch (SuperNotCalledException e) {
...
} catch (Exception e)
...
}
...
}
...
}
由上述源码可知,这个performLaunchActivity做的事情还是挺多的,创建Activity 对象,创建Applciation对象,创建Context对象,初始化Window对象,以及回调activity对象的onCreate、onStart方法。
activity中的attach方法的完整源码
package android.app;
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback, WindowControllerCallback {
...
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) {
//把在performLaunchActivity中创建的Context对象绑定的ContextWrapper类中的mBase变量上
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
// 创建PhoneWindow对象,一个Activity对应的那一个PhoneWindow
mWindow = new PhoneWindow(this, window);
mWindow.setWindowControllerCallback(this);
//窗口事件的回调方法,文档中说,这个Callback用于拦截key事件和窗口中其他动态操作
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);
}
//将主线程记录在Activity的mUiThread
mUiThread = Thread.currentThread();
//记录ActivityThread对象以及给Activity的很多变量进行初始化
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
if (voiceInteractor != null) {
if (lastNonConfigurationInstances != null) {
mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
} else {
mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
Looper.myLooper());
}
}
//为Window设置WindowManager
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
if (mParent != null) {
mWindow.setContainer(mParent.getWindow());
}
//Window中记录了WindowManager对象,Activity也记录了一下
mWindowManager = mWindow.getWindowManager();
mCurrentConfig = config;
}
...
}
根据上述源码可以知道,Activity的attach方法主要做了这些事情:给ContextWrapper中的成员变量mBase赋值、创建Window对象并设置回调函数,给Activity的众多成员变量赋值,为Window设置WindowManager对象等。
下面看一下,Window的setWindowManager方法:
package android.view;
public abstract class Window {
...
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
//为window中的一些变量赋值
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
//在现有WindowManager的基础上又创建了WindowManager对象
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
...
}
在为Window设置WindowManager的过程中,其实有两个WindowManager对象,一个是通过getSystemService(Context.WINDOW_SERVICE)获取到的,另一个是通过第一个得到的WindowManager对象调用createLocalWindowManager方法获取的。这两个WindowManager对象的不同在于,第二个的成员变量mParentWindow是有值的,最终负责管理Window的也是第二个WindowManager对象。
2. Activity回调onCreate
在上面介绍performLaunchActivity方法做的事情时,说它在执行了activity.attach方法之后会回调Activity对象的onCreate方法。在onCreate方法一般会调用setContentView方法,那setContentView背后到底做了哪些事呢?
Activity的setContentView方法(AppcompatActivity这里就不说了,和Activity的setContentView是有差异的):
package android.app;
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback, WindowControllerCallback {
...
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
...
public Window getWindow() {
return mWindow;
}
...
}
可以看到,getWindow方法直接返回了mWindow,而它赋值的地方就是在Activity的attach方法中:mWindow = new PhoneWindow(this, window)。也就是说,Activity的setContentView方法其实就是去调用PhoneWindow的setContentView方法,那就去看一下PhoneWindow的setContentView的方法:
package com.android.internal.policy;
public class PhoneWindow extends Window implements MenuBuilder.Callback {
...
@Override
public void setContentView(int layoutResID) {
//DecorView分为两部分:标题和内容。内容其实就是这里的mContentParent
//mContentParent为空说明还没有DecorView,那就去创建DecorView
//非空的话,要移除所有的布局,因为要给它设置新的布局(layoutResID)了
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
//因为执行了上面的代码,到这里mContentParent就不为空了
// 如果内容显示时需要动画就执行Scence相关代码,否则就直接使用填充器填充就可以了
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
mLayoutInflater.inflate(layoutResID, mContentParent);
}
//执行到这里mContentParent就已经填充了layoutResID中的内容了
//让DecorView的内容区域延伸到systemUi下方,防止在扩展时被覆盖,达到全屏、沉浸等不同体验效果(并不是很理解)
mContentParent.requestApplyInsets();
//回调Callback中的onContentChanged方法
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
...
}
可见window的setContentView方法做的事情是:没有DecorView就创建DecorView,把布局内容放到mContentParent中,然后回调窗口的onContentChanged方法。
3. Activity回调onResume
上面说了performLaunchActivity的方法,这里看一下,ActivityThread中调用performLaunchActivity的地方:handleLaunchActivity
package android.app;
public final class ActivityThread {
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
//初始化WindowManagerGlobal
WindowManagerGlobal.initialize();
//这里就是调用performLaunchActivity的地方,上面已经讲述了该方法的功能
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
...
//在这里会回调Activity对象的onResume方法
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
...
}else{
...
}
...
}
...
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
...
//真正回调onResume的方法
r = performResumeActivity(token, clearHide, reason);
if (r != null) {
...
if (r.activity.mVisibleFromClient) {
//这里的makeVisible方法就是使界面显示的方法了
r.activity.makeVisible();
}
...
}
...
}
...
}
Activity的makeVisible方法:
package android.app;
public class Activity extends ContextThemeWrapper
implements LayoutInflater.Factory2,
Window.Callback, KeyEvent.Callback,
OnCreateContextMenuListener, ComponentCallbacks2,
Window.OnWindowDismissedCallback, WindowControllerCallback {
...
void makeVisible() {
if (!mWindowAdded) {
//获取WindowManager
ViewManager wm = getWindowManager();
//将DecorView添加到Window中
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
...
}
继续看WindowManagerImpl的addView方法:
package android.view;
public final class WindowManagerImpl implements WindowManager {
...
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
//调用的是WindowManagerGlobal对象的addView方法,
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
...
}
由上述addView方法,可知WindowManager也没有具体实现addView的方法,而是再次调用了WindowManagerGlobal对象的addView方法。好吧,那就继续看WindowManagerGlobal对象的addView方法:
package android.view;
public final class WindowManagerGlobal {
...
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
//下面3个if是验证非空以及类型
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
if (display == null) {
throw new IllegalArgumentException("display must not be null");
}
if (!(params instanceof WindowManager.LayoutParams)) {
throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
}
//设置params相关
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
if (parentWindow != null) {
//调整窗口布局
parentWindow.adjustLayoutParamsForSubWindow(wparams);
} else {
// If there's no parent, then hardware acceleration for this view is
// set from the application's hardware acceleration setting.
final Context context = view.getContext();
if (context != null
&& (context.getApplicationInfo().flags
& ApplicationInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
wparams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
}
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
// 系统属性的监听
if (mSystemPropertyUpdater == null) {
mSystemPropertyUpdater = new Runnable() {
@Override public void run() {
synchronized (mLock) {
for (int i = mRoots.size() - 1; i >= 0; --i) {
mRoots.get(i).loadSystemProperties();
}
}
}
};
SystemProperties.addChangeCallback(mSystemPropertyUpdater);
}
//好像是预防某种关闭没彻底
int index = findViewLocked(view, false);
if (index >= 0) {
if (mDyingViews.contains(view)) {
// Don't wait for MSG_DIE to make it's way through root's queue.
mRoots.get(index).doDie();
} else {
throw new IllegalStateException("View " + view
+ " has already been added to the window manager.");
}
// The previous removeView() had not completed executing. Now it has.
}
// If this is a panel window, then find the window it is being
// attached to for future reference.
if (wparams.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW &&
wparams.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
final int count = mViews.size();
for (int i = 0; i < count; i++) {
if (mRoots.get(i).mWindow.asBinder() == wparams.token) {
panelParentView = mViews.get(i);
}
}
}
//创建当前DecorView对象的ViewRootImpl对象
root = new ViewRootImpl(view.getContext(), display);
//把经过处理后的params设置给DecorView
view.setLayoutParams(wparams);
//存储当前应用进程的所有DecorView、ViewRootImpl、params
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
}
// do this last because it fires off messages to start doing things
try {
//进程间通信,真正地显示在Display上
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
synchronized (mLock) {
final int index = findViewLocked(view, false);
if (index >= 0) {
removeViewLocked(index, true);
}
}
throw e;
}
}
...
}
WindowManagerGlobal是管理app进程中所有的窗口的,相关的DecorView、ViewRootImpl、WindowManager.LayoutParams会存储到WindowManagerGlobal中的相关成员变量中进行管理
private final ArrayList mViews = new ArrayList();
private final ArrayList mRoots = new ArrayList();
private final ArrayList mParams =
new ArrayList();
代码确实有点儿多,下面setView方法只关注两个点:
package android.view;
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.HardwareDrawCallbacks {
...
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
...
//这里会走View的绘制流程
requestLayout();
...
//这里利用Binder机制与WindowManagerService跨进程通信,真正地显示在屏幕上
es = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(),
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mInputChannel);
...
}
...
}
总结
整个流程涉及到的源码以及细节都太多太多,后续随着对Window机制了解的深入,会逐渐完善这篇博客。