Activity.setContentView()已经解释了三者的关系。
Activity.attach()创建了window的实现类PhoneWindow
final void attach(...){
mWindow = new PhoneWindow(this, window, activityConfigCallback);
}
也就是说每个Activity对应到一个window实例PhoneWindow。setContentView()方法设置xml布局其实就是创建顶层布局DecorView,并按需创建ActionBar,menu,添加id为content的FrameLayout。然后通过LayoutInflater解析xml成view树,最后将View树添加到content。但是这里并没有解释view树何时绘制。上篇说到创建DecorView时调用了PhoneWindow.setContentView()将DecorView关联到window。那么问题来了,DecorView关联到window后何时绘制显示的呢?
我们都知道,Activity在onResume()时真正显示,先找到onResume()回调的地方。下面看源码细节。
ActivityThread.handleResumeActivity()
public void handleResumeActivity(...){
...
//回调onResume()
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
...
final Activity a = r.activity
...
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
...
r.activity.makeVisible();
}
Activity.makeVisible()
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
mDecor.setVisibility(View.VISIBLE);
}
Activity.getWindowManager()方法返回WindowManager
public WindowManager getWindowManager() {
return mWindowManager;
}
mWindowManager在Activity.attach()中初始化
final void attach(...){
...
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
mWindowManager = mWindow.getWindowManager();
}
Window.setWindowManager()
public void setWindowManager(WindowManager wm, IBinder appToken, String appName) {
setWindowManager(wm, appToken, appName, false);
}
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
//实现类WindowManagerImpl
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
WindowManager继承自ViewManager接口
ViewManager接口方法
public void addView(View view, ViewGroup.LayoutParams params);
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
public void removeView(View view);
很明显WindowManager是view的直接管理者,而WindowManager实现类是WindowManagerImpl。
下面看WindowManagerImpl
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.updateViewLayout(view, params);
}
public void removeView(View view) {
mGlobal.removeView(view, false);
}
内部调用WindowManagerGlobal.addView()
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
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");
}
ViewRootImpl root;
View panelParentView = null;
synchronized (mLock) {
//ViewRootImpl
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
try {
//ViewRootImpl.setView()
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
ViewRootImpl.setView()
public void setView(...){
...
requestLayout();
...
}
ViewRootImpl.requestLayout()
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
checkThread();
mLayoutRequested = true;
scheduleTraversals();
}
}
ViewRootImpl.scheduleTraversals()
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
mTraversalRunnable
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
ViewRootImpl.doTraversal()
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
ViewRootImpl.performTraversals()开启绘制流程
private void performTraversals() {
//绘制流程
performMeasure(...);
performLayout(...);
performDraw();
}
最后总结下三者关系:每个Activity对应到一个Window实例,Window是窗口的抽象,其实现类是PhoneWindow,在Activity.attach()方法中初始化。Activity.setContentView()设置xml布局时,会创建DecorView真正的顶层布局,然后解析xml成view树添加到id为content的DecorView子view。在onResume()方法调用处,ActivityThread中Window通过WindowManager调用addview()添加DecorView,间接调用到ViewRootImpl.setView(),最终调用ViewRootImpl.performTraversals()开始绘制view树展示布局。
也就是说Window是view的管理者,通过WindowManager的三个方法addView()、updateViewLayout()、removeView()管理view,而ViewRootImpl才是真正的绘制入口。







网友评论