1、DecorView 创建
创建 PhoneWindow 对象。 为 PhoneWindow 设置 WindowManager 对象。 为 PhoneWindow 创建一个 DecorView 对象。 为 DecorView 的 ContentView 设置 activity 中设置的布局文件。
Activity.java
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) {
attachBaseContext(context);
mFragments.attachHost(null /*parent*/);
// 1.初始化 Window 对象。
mWindow = new PhoneWindow(this, window, activityConfigCallback);
// 2.设置回调,向 Activity 分发事件。
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
...
// 3.mWindow 设置 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());
}
// 4.初始化 WindowManager 对象。
mWindowManager = mWindow.getWindowManager();
}
// 设置 ContentView 布局
public void setContentView(@LayoutRes int layoutResID) {
// 为 mWindow 设置布局
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
PhoneWindow.java
// mWindow 设置布局。
@Override
public void setContentView(int layoutResID) {
// 1.mContentParent 为 null,创建一个 DecorView。
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
// 不为 null,移除其中所有 View。
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
getContext());
transitionTo(newScene);
} else {
// 2.为 mContentParent 添加布局。
mLayoutInflater.inflate(layoutResID, mContentParent);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
// 3.回调通知,内容改变。
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
// 创建一个 DecorView
private void installDecor() {
mForceDecorInstall = false;
if (mDecor == null) {
// 1.生成 DecorView。
mDecor = generateDecor(-1);
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
} else {
mDecor.setWindow(this);
}
if (mContentParent == null) {
// 2.为 DecorView 设置 mContentParent 布局。
mContentParent = generateLayout(mDecor);
// Set up decor part of UI to ignore fitsSystemWindows if appropriate.
mDecor.makeOptionalFitsSystemWindows();
final DecorContentParent decorContentParent = (DecorContentParent) mDecor.findViewById(
R.id.decor_content_parent);
。。。
}
// 生成 DecorView。
protected DecorView generateDecor(int featureId) {
。。。
return new DecorView(context, featureId, this, getAttributes());
}
// 生成 DecorView 的 mContentParent。
protected ViewGroup generateLayout(DecorView decor) {
// 1.获取 Window 主题信息。
TypedArray a = getWindowStyle();
。。。
// Inflate the window decor.
// 2. 根据主题样式,加载窗口布局。
int layoutResource;
int features = getLocalFeatures();
。。。
// 3.加载 layoutResource,往 DecorView 添加子 View。
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
// 4.获取 DecorView 的内容布局 mContentParent 。
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
// ...设置 TitleView
return contentParent;
}
2、DecorView 显示
启动 Activity 后,主线程会调用 handleResumeActivity()。 将 DecorView 对象添加到 WindowManager。 创建 ViewRootImpl 对象。 WindowManager 将 DecorView 交给 ViewRootImpl 对象。 ViewRootImpl 通过 Handler 向主线程发送消息遍历绘制视图:performTraversals() 执行 View 的绘制流程。
ActivityThread.java
final void handleResumeActivity(IBinder token,
boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {
r = performResumeActivity(token, clearHide, reason);
if (r != null) {
final Activity a = r.activity;
。。。
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
// 1.获取 window 的 DecorView 对象。
View decor = r.window.getDecorView();
// 2.DecorView 设置不可见。
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
。。。
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
// 3.将 DecorView 添加到 WindowManager。
wm.addView(decor, l);
} else {
// The activity will get a callback for this {@link LayoutParams} change
// earlier. However, at that time the decor will not be set (this is set
// in this method), so no action will be taken. This call ensures the
// callback occurs with the decor set.
a.onWindowAttributesChanged(l);
}
}
// 4.设置 DecorView 可见。
if (!r.activity.mFinished && willBeVisible
&& r.activity.mDecor != null && !r.hideForNow) {
。。。
if (r.activity.mVisibleFromClient) {
r.activity.makeVisible();
}
}
// Tell the activity manager we have resumed.
}
Activity.java
void makeVisible() {
if (!mWindowAdded) {
ViewManager wm = getWindowManager();
// 1.将 DecorView 添加到 WindowManager。
wm.addView(mDecor, getWindow().getAttributes());
mWindowAdded = true;
}
// 2.设置 DecorView 可见。
mDecor.setVisibility(View.VISIBLE);
}
WindowManagerImpl.java
public final class WindowManagerImpl implements WindowManager {
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
}
WindowManagerGlobal.java
public final class WindowManagerGlobal {
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
。。。
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
。。。
// 1.创建 ViewRootImpl 对象。
ViewRootImpl root;
root = new ViewRootImpl(view.getContext(), display);
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 {
// 2.WindowManager 将 DecorView 对象交给 ViewRootImpl 绘制 View
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
}
ViewRootImpl.java
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
synchronized (this) {
requestLayout();
}
@Override
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
// 1.检查是否在主线程。
checkThread();
// mLayoutRequested 表示是否 measure 和 layout 布局。
mLayoutRequested = true;
scheduleTraversals();
}
}
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 1.类似 Handler.post() 方法,mTraversalRunnable 处理绘制流程。
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
// 1.开始 View 的3大流程:Measure、Layout、Draw。
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
// W 类为 Binder 的 Native 端。用于接收 WMS 处理操作;W 类接收的方法是在线程池中,可以通过 Handler 将事件处理切换到主线程中。
static class W extends IWindow.Stub {
}