Android Window创建过程
先了解下几个概念
Window
1.Window是顶级窗口外观和行为策略的抽象基类。 是被添加到WindowManager的顶级视图。
2.它提供了标准的 UI 策略,例如背景、标题区域、默认键处理等略。
3.目前仅有的实现类是PhoneWindow。
4.View(Activity、Toast、Dialog)需要依赖于Window
WindowManager
1.Window的管理者,或者说,Window中View的管理者,Window所需要展示的内容是由View来承载的
2.它的具体实现是WindowManagerImpl,用getSystemService(Context.WINDOW_SERVICE)来获取
3.继承ViewManager
WindowManagerImpl在SystemServiceRegistry类中创建
static {
...
registerService(Context.WINDOW_SERVICE, WindowManager.class,
new CachedServiceFetcher<WindowManager>() {
@Override
public WindowManager createService(ContextImpl ctx) {
return new WindowManagerImpl(ctx);
}});
...
通过getSystemService(Context.WINDOW_SERVICE)获取
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManagerService
1.系统服务,继承继承 IWindowManager.Stub,负责协调Window的层级、显示及事件派发等
2.WindowManager是本地端的管理者,负责与WindowManagerService进行交互,这是一个IPC过程
在SystemServer启动的时候,会创建WindowManagerService并注册到ServiceManager中:
// 在main()方法中会调用startOtherServices()
private void startOtherServices() {
...
wm = WindowManagerService.main(context, inputManager, mFactoryTestMode !=
FactoryTest.FACTORY_TEST_LOW_LEVEL,!mFirstBoot, mOnlyCore);
ServiceManager.addService(Context.WINDOW_SERVICE, wm);
...
}
WindowManagerGlobal
1.WindowManagerImpl实际上是将工作委托给了WindowManagerGlobal来完成
2.WindowManagerGlobal中主要对View、ViewRootImpl以及LayoutParams进行管理
// view
private final ArrayList<View> mViews = new ArrayList<View>();
// ViewRootImpl
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
// 参数
private final ArrayList<WindowManager.LayoutParams> mParams = new ArrayList<WindowManager.LayoutParams>();
// 即将移除的view
private final ArraySet<View> mDyingViews = new ArraySet<View>();
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
...
}
ViewRootImpl
1.ViewRootImpl不是View,它是顶级View的管理者。
2.每一个ViewRootImpl 都对应着一个ViewTree ,通过它来完成View的绘制及显示过程。
3.Window与View通过ViewRootImpl建立起联系
Window创建过程
ActivityThread
启动Activity时,ActivityThread会处理以下几件事:
1.拿到Activity一些组件信息,然后通过Instrumentation反射创建Activity
2.调用Activity的attach来完成Window的创建等工作,
3.回调onCreate生命周期方法。
4.回调onResume
5.通过WindowManager.addView添加Window(具体看后面讲解)
public final class ActivityThread extends ClientTransactionHandler {
// 保存所有Activity的相关信息
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
// Activity启动
@Override
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
...
// 创建activity之前进行WindowManagerGlobal的初始化
WindowManagerGlobal.initialize();
// 创建activity 及调用onCreate
Activity a = performLaunchActivity(r, customIntent);
}
// Activity启动, onCreate
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent){
ActivityInfo aInfo = r.activityInfo;
// ... 拿到相关package、组件等信息
// 创建上下文对象,实际创建的是ContextImpl对象
ContextImpl appContext = createBaseContextForActivity(r);
// ... 反射来创建Activity
Activity activity = ...
try {
// LoadedApk创建Application对象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
Window window = null;
// activity 重启,拿到上一次的Window,并在PhoneWindow复用之前的DecorView
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
// 这里通过调用 activity.attach 创建一个PhoneWindow
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);
...
// 回调onCreate
mInstrumentation.callActivityOnCreate(activity, r.state);
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
}
...
return activity;
}
@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
...
// onResume
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
if (r == null) {
return;
}
if (r.window == null && !a.mFinished && willBeVisible) {
// 获取的Window为PhoneWindow
r.window = r.activity.getWindow();
// 获取DecorView
View decor = r.window.getDecorView();
// 设为不可见
decor.setVisibility(View.INVISIBLE);
// 通过WindowManager添加到窗体
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
wm.addView(decor, l);
...
}
...
if (r.activity.mVisibleFromClient) {
// 会调用decor.setVisibility(View.VISIBLE)设置为可见
r.activity.makeVisible();
}
}
public ActivityClientRecord performResumeActivity(IBinder token, boolean finalStateRequest,
String reason) {
final ActivityClientRecord r = mActivities.get(token);
...
// onResume
r.activity.performResume(r.startsNotResumed, reason);
...
}
// Activity内部类,每一个Activity对应一个ActivityClientRecord
// 存储在mActivities中
public static final class ActivityClientRecord {
// activity的token
public IBinder token;
Intent intent;
// onSaveInstance数据保存在这里
Bundle state;
Activity activity;
// activity附加到的Window,handleResumeActivity进行赋值
Window window;
// 保存由于配置更改而导致页面销毁时的一些状态,包括ViewModelStore,Fragment等
Activity.NonConfigurationInstances lastNonConfigurationInstances;
// activity重启,拿到上一次的Window,handleLaunchActivity初始化
Window mPendingRemoveWindow;
// activity重启,拿到上一次的WindowManager,handleLaunchActivity初始化
WindowManager mPendingRemoveWindowManager;
}
}
// Activity静态内部类,保存由于配置更改而导致页面销毁时的一些状态
static final class NonConfigurationInstances {
// 保存ViewModelStore
Object activity;
// 保存Fragment
HashMap<String, Object> children;
FragmentManagerNonConfig fragments;
ArrayMap<String, LoaderManager> loaders;
VoiceInteractor voiceInteractor;
}
// ComponentActivity静态内部类,用于保存ViewModelStore
static final class NonConfigurationInstances {
Object custom;
ViewModelStore viewModelStore;
}
Activity
1.完成PhoneWindow的创建
2.通过setContentView,在PhoneWindow中创建了DecorView(具体看后面)
public class Activity extends ...{
private Window mWindow;
private WindowManager mWindowManager;
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) {
// 创建Window(PhoneWindow),并传入重启前的window
mWindow = new PhoneWindow(this, window);
// 设置各种Callback
mWindow.setWindowControllerCallback(this);
// this即activity,存在Window的mCallback中
mWindow.setCallback(this);
...
// 设置WindowManager,实际上设置的是WindowManagerImpl
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
mWindowManager = mWindow.getWindowManager();
...
}
public void setContentView(View view, ViewGroup.LayoutParams params) {
getWindow().setContentView(view, params);
initWindowDecorActionBar();
}
}
PhoneWindow
1.创建DecorView
2.将View填充到mContentParent中
public class PhoneWindow extends Window {
public PhoneWindow(Context context, Window preservedWindow,
ActivityConfigCallback activityConfigCallback) {
this(context);
// 复用重启前的View
if (preservedWindow != null) {
mDecor = (DecorView) preservedWindow.getDecorView();
...
}
}
@Override
public void setContentView(View view, ViewGroup.LayoutParams params) {
// mContentParent为ID_ANDROID_CONTENT
if (mContentParent == null) {
// 创建DecorView
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
...
// 将Activity.setContentView添加的布局,填充到mContentParent中
mContentParent.addView(view, params);
...
}
// 在ActivityThread的handleResumeActivity中会获取DecorView添加到WindowManager中
// 如果没调用setContentView,当调用getDecorView会默认创建一个DecorView
// 所以不管是那种情况都会调用导致DecorView的创建,不过只会创建一次
@Override
public final @NonNull View getDecorView() {
if (mDecor == null || mForceDecorInstall) {
installDecor();
}
return mDecor;
}
// 创建 DecorView
private void installDecor() {
if (mDecor == null) {
// 用来创建DecorView
mDecor = generateDecor(-1);
...
} else {
mDecor.setWindow(this);
}
if (mContentParent == null) {
// 内容布局,android.R.content
mContentParent = generateLayout(mDecor);
...
}
// 设置标题样式等
...
}
}
WindowManagerGlobal
由ActivityThread -> handleResumeActivity 可知:
在onResume之后,将DecorView添加到WindowManage(WindowManagerGlobal)
WindowManagerGlobal创建ViewRootImpl,并将DecorView设置到ViewRootImpl
WindowManager.LayoutParams l = r.window.getAttributes();
wm.addView(decor, l);
public final class WindowManagerGlobal {
private static IWindowManager sWindowManagerService;
private static IWindowSession sWindowSession;
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
...
// 创建ViewRootImpl
ViewRootImpl root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
...
// 给ViewRootImpl添加DecorView
// 最后执行这个操作,是因为它会触发消息
root.setView(view, wparams, panelParentView, userId);
}
// 通过wms创建一个类型为Session的Binder对象
public static IWindowSession getWindowSession() {
if (sWindowSession == null) {
...
IWindowManager windowManager = getWindowManagerService();
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
});
}
return sWindowSession;
}
}
// 获取wms的代理
public static IWindowManager getWindowManagerService() {
if (sWindowManagerService == null) {
sWindowManagerService = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
...
return sWindowManagerService;
}
}
}
ViewRootImpl
通过IWindowSession于WindowManagerService交互,完成window的添加等操作
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
// mWindowSession是一个通过WMS获取的Binder对象,真正的实现类是Session
final IWindowSession mWindowSession;
View mView;
W mWindow = new W(this);
// mWindowSession初始化
public ViewRootImpl(Context context, Display display) {
this(context, display, WindowManagerGlobal.getWindowSession(), false);
}
// 将Window添加到窗口管理器
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
int userId) {
mView = view;
...
// 在添加到窗口管理器之前请求一次布局
// 以确保我们从系统接收任何其他事件之前进行重新布局。
requestLayout();
// ViewRootImpl 通过 IWindowSession 与 WMS 进行交互的
// 这是一个IPC的过程,基于Binder的跨进程通信。
// 通过调用 addToDisplay, 将 mWindow 等参数传递给 WindowManagerService
// 内部执行Window的添加等操作
mWindowSession.addToDisplayAsUser(mWindow, ....);
...
// 将ViewRootImpl设置为DecorView的parent (继承ViewParent)
view.assignParent(this);
...
}
static class W extends IWindow.Stub {
...
}
}
1.Window的添加是通过IWindowSession建立起与WMS的连接。
2.IWindowSession是一个Binder对象,其实现是Session,Session内部通过调用WMS的addWindow方法进行
Window的添加等操作,Window的状态保存到了WindowState中
3.当应用启动第一个activity的时候,会请求WMS服务建立Binder进程间通信服务,WMS创建一个类型为
Session的Binder对象,并将这个Binder对象返回给应用进程
Window的添加大致流程:
-> WindowManager(WindowManagerImpl)
-> WindowManagerGlobal>addView
-> ViewRootImpl>setView>IWindowSession>addToDisplay
-> (IPC)Session>addToDisplay
-> WindowManagerService>addWindow
总结
1.Activity启动时,由ActivityThread.handleLaunchActivity创建Activity,并执行Activity.attach方法,
然后回调onCreate
2.Activity.attach创建一个PhoneWindow
3.PhoneWindow创建DecorView,并将contentView添加到DecorView
4.ActivityThread.handleResumeActivity,回调onResume,然后获取window的DecorView添加到WM中
5.WM创建ViewRootImpl,并调用ViewRootImpl.setView将DecorView设置到ViewRootImpl中
6.ViewRootImpl调用requestLayout()方法来请求绘制布局
7.ViewRootImpl通过WMS获取Session的代理对象IWindowSession
8.IWindowSession将window的binder代理W添加到WMS中