上一篇讲了下activity setcontentView的流程,布局中的view被创建后并添加到了decorView上,本文讲解后续decorview是如何显示的。
上篇文章:Android setContentView 梳理-CSDN博客
setcontentView设置的布局最后显示在窗口上的,一般,activity在onResume时,就认为已经处于显示状态了,其实不是,分析相关源码。
onResume从哪里被调用的
//从ActivityThresd.java分析
handleResumeActivity()
performResumeActivity(r, finalStateRequest, reason)
r.activity.performResume(r.startsNotResumed, reason);
activity的onResume()被执行
decorView如何显示的
对decorView的处理是wm.addView()。
//ActivityThresd.java
@Override
public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
boolean isForward, String reason) {
//......
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;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
//......
a.mWindowAdded = true;
wm.addView(decor, l);//对decorView的处理
//......
}
WindowManager是一个接口,常见的实现有WindowManagerImpl.
/**
* The interface that apps use to talk to the window manager.
* <p>
* Each window manager instance is bound to a {@link Display}. To obtain the
* <code>WindowManager</code> associated with a display,
* call {@link Context#createWindowContext(Display, int, Bundle)} to get the display's UI context,
* then call {@link Context#getSystemService(String)} or {@link Context#getSystemService(Class)} on
* the UI context.
* <p>
* The simplest way to show a window on a particular display is to create a {@link Presentation},
* which automatically obtains a <code>WindowManager</code> and context for the display.
*/
@SystemService(Context.WINDOW_SERVICE)
public interface WindowManager extends ViewManager {
//......}
wm.addView()
WindowManagerGlobal只有一个实例,管理整个进程的所有窗口的信息
ViewRootImpl管理当前窗口的信息
//WindowManagerImpl.java
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyTokens(params);
mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
mContext.getUserId());
}
//WindowManagerGlobal.java
//Provides low-level communication with the system window manager for operations that are not associated with any particular context. 为与任何特定上下文无关的操作提供与系统窗口管理器的低级通信。
@UnsupportedAppUsage
private final ArrayList<View> mViews = new ArrayList<View>();
@UnsupportedAppUsage
private final ArrayList<ViewRootImpl> mRoots = new ArrayList<ViewRootImpl>();
@UnsupportedAppUsage
private final ArrayList<WindowManager.LayoutParams> mParams =
new ArrayList<WindowManager.LayoutParams>();
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow, int userId) {
//......
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
//......
ViewRootImpl root;
//......
if (windowlessSession == null) {
root = new ViewRootImpl(view.getContext(), display);
} else {
root = new ViewRootImpl(view.getContext(), display,
windowlessSession);
}
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView, userId);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
ViewRootImpl.setView
//ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
int userId) {
mView = view;
//......
requestLayout();
//......
res = mWindowSession.addToDisplayAsUser(mWindow, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId,
mInsetsController.getRequestedVisibilities(), inputChannel, mTempInsets,
mTempControls);
//......
view.assignParent(this);//根View是ViewRootImpl
//......
}
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
public ViewRootImpl(@UiContext Context context, Display display, IWindowSession session,
boolean useSfChoreographer) {
//......
mThread = Thread.currentThread();//哪个线程创建的ViewRootImpl 哪个view可以刷新
//......
}
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
performTraversals();//开始绘制流程了
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
performTraversals()
windowSizeMayChange |= measureHierarchy(host, lp, mView.getContext().getResources(),
desiredWindowWidth, desiredWindowHeight);
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
performLayout(lp, mWidth, mHeight);
performDraw()