WMS流程
Window & Activity & DecorView & ViewRoot关系
- Activity:
- 处理器,控制生命周期和处理事件
- 1个Activity包含1个Window
- 通过回调与Window、View交互
- Window:
- 实现类是PhoneWindow
- 视图的承载器,用于管理View的显示
- PhoneWindow内部包含一个DecorView
- 内部通过WindowManager管理UI,将DecorView交给ViewRoot
- DecorView:
- 顶层View,本质是FrameLayout
- 显示和加载布局
- View的事件最先经过DecorView,再分发到子View
- ViewRoot:
- ViewRootImpl是其实现类
- 用于连接
WindowManager
和DecorView
- 完成View的三大流程:测量、布局、绘制
流程图
源码分析
ActivityThread#handleLaunchActivity()
- 初始化WMS服务
- 调用
performLaunchActivity()
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
WindowManagerGlobal.initialize();
final Activity a = performLaunchActivity(r, customIntent);
return a;
}
ActivityThread#performLaunchActivity()
- 创建Activity
- 调用
Activity#attach()
- 回调
Activity#onCreate()
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
} catch (Exception e) {
}
if (activity != null) {
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, r.configCallback,
r.assistToken);
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
}
return activity;
}
Activity#attach()
- 创建PhoneWindow对象,PhoneWindow是Window的实现类
- 创建WindowManageImpl,WindowManageImpl是WindowManage的实现类
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) {
attachBaseContext(context);
mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(mWindowControllerCallback);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
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());
}
mWindowManager = mWindow.getWindowManager();
}
Activity#setContentView()
- 最终调用
PhoneWindow#setContentView()
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
PhoneWindow#setContentView()
- 创建DecorView
- 将Activity的XML布局加载到DecorView中
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
mLayoutInflater.inflate(layoutResID, mContentParent);
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
}
PhoneWindow#installDecor()
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
mDecor = generateDecor(-1);
} else {
mDecor.setWindow(this);
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
}
}
protected DecorView generateDecor(int featureId) {
return new DecorView(context, featureId, this, getAttributes());
}
protected ViewGroup generateLayout(DecorView decor) {
TypedArray a = getWindowStyle();
int layoutResource;
int features = getLocalFeatures();
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
mContentRoot = (ViewGroup) in;
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
return contentParent;
}
ActivityThread#handleResumeActivity()
- 回调
Activity#onResume()
- 获取PhoneWindow和DecorView,将Activity与DecorView绑定
- 调用
WindowManageImpl#addView()
将DecorView传入
public void handleResumeActivity(IBinder token, boolean finalStateRequest,
boolean isForward, String reason) {
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
final Activity a = r.activity;
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();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l);
}
}
}
if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
}
WindowManagerImpl#addView()
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
mContext.getUserId());
}
WindowManagerGlobal#addView()
- 创建ViewRootImpl
- 将DecorView交给ViewRootImpl处理
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
if (parentWindow != null) {
parentWindow.adjustLayoutParamsForSubWindow(wparams);
} else {
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;
synchronized (mLock) {
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
try {
root.setView(view, wparams, panelParentView, userId);
} catch (RuntimeException e) {
}
}
}
ViewRootImpl#setView()
- ViewRootImpl最终会触发遍历操作
- 依次执行View的测量、布局、绘制流程
public void setView(View view, WindowManager.LayoutParams attrs,
View panelParentView, int userId) {
requestLayout();
}
ViewRootImpl#requestLayout()
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
ViewRootImpl#doTraversal()
- 最终调用
ViewRootImpl#performTraversals()
void doTraversal() {
performTraversals();
}
ViewRootImpl#performTraversals()
- 依次调用
performMeasure()
/ performLayout()
/ performDraw()
完成View的三大流程
private void performTraversals() {
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
performLayout(lp, mWidth, mHeight);
mAttachInfo.mTreeObserver.dispatchOnGlobalLayout();
performDraw();
}
ViewRootImpl#performMeasure()
private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
if (mView == null) {
return;
}
mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
ViewRootImpl#performLayout()
private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,
int desiredWindowHeight) {
final View host = mView;
if (host == null) {
return;
}
host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
}
ViewRootImpl#performDraw()
private void performDraw() {
boolean canUseAsync = draw(fullRedrawNeeded);
}
private boolean draw(boolean fullRedrawNeeded) {
drawSoftware(surface, mAttachInfo, xOffset, yOffset,
scalingRequired, dirty, surfaceInsets)
}
private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
boolean scalingRequired, Rect dirty, Rect surfaceInsets) {
mView.draw(canvas);
}
总结
- 在performLaunchActivity阶段,会创建Activity、PhoneWindow、WindowManageImpl,并回调
Activity#onCreate()
,接着执行setContentView流程,创建DecorView并将XML布局解析加载到DecorView中。 - 在handleResumeActivity阶段,会调用
Activity#onResume()
,将Activity与DecorView建立关联,创建ViewRootImpl,将DecorView交给ViewRootImpl处理,最终ViewRootImpl依次执行View的三大流程。
常见问题
invalidate和requestLayout区别
- requestLayout:requestLayout会直接递归调用父View的requestLayout,直到ViewRootImpl,然后触发ViewRoomtImpl的
peformTraversals()
方法,会依次调用onMeasure()
和onLayout()
,不一定会触发onDraw()
;当在layout过程中发现四个顶点(left、top、right、bottom)和以前不一样时,会触发invalidate,调用onDraw,进行重新绘制。 - invalidate:View的invalidate不会触发ViewRootImpl的invalidate,而是递归调用父View的invalidateChildParent,知道ViewRootImpl的invalidateChildParent,然后触发perfromTraversals,由于mLayoutRequested为false,不会调用onMeasure和onLayout,只会调用onDraw,ViewGroup的onDraw不会被调用(除非设置背景),倒置当前View被重绘。