初始化WindowManagerService
-
ActivityThread
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) { ...... // Initialize before creating the activity WindowManagerGlobal.initialize(); Activity a = performLaunchActivity(r, customIntent); ... }
-
android.view.WindowManagerGlobal
public static void initialize() { getWindowManagerService(); } public static IWindowManager getWindowManagerService() { synchronized (WindowManagerGlobal.class) { if (sWindowManagerService == null) { sWindowManagerService = IWindowManager.Stub.asInterface( ServiceManager.getService("window")); try { sWindowManagerService = getWindowManagerService(); ValueAnimator.setDurationScale(sWindowManagerService.getCurrentAnimatorScale()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } return sWindowManagerService; } }
获取WindowManagerService。
获取窗口并初始化
-
Activity
final void attach(...) { attachBaseContext(context); ...... mWindow = new PhoneWindow(this, window); mUiThread = Thread.currentThread(); 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(); mCurrentConfig = config; }
-
android.view.Window
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
......
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
public WindowManagerImpl createLocalWindowManager(Window parentWindow) {
return new WindowManagerImpl(mContext, parentWindow);
}
public WindowManager getWindowManager() {
return mWindowManager;
}
可以看出,mWindowManager其实是一个WindowManagerImpl实例。
给Window添加Activity布局
-
android.app.ActivityThread
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) { ...... // TODO Push resumeArgs into the activity for consideration 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(); 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; l.softInputMode |= forwardBit; if (a.mVisibleFromClient && !a.mWindowAdded) { a.mWindowAdded = true; wm.addView(decor, l); } } // The window is now visible if it has been added, we are not // simply finishing, and we are not starting another activity. if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) { ... ViewManager wm = a.getWindowManager(); View decor = r.window.getDecorView(); wm.updateViewLayout(decor, l); } ...... } }
可以看出,当首次加载布局时,会走到:
wm.addView(decor, l);
这里面,从上面可以知道,wm其实是一个WindowManagerImpl对象。看看源码:
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
mGlobal是一个WindowManagerGlobal对象。
-
android.view.WindowManagerGlobal
public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { ...... synchronized (mLock) { root = new ViewRootImpl(view.getContext(), display); mRoots.add(root); } root.setView(view, wparams, panelParentView); ...... }
-
android.view.ViewRootImpl
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { synchronized (this) { if (mView == null) { mView = view; ....... // Schedule the first layout -before- adding to the window // manager, to make sure we do the relayout before receiving // any other events from the system. requestLayout(); ....... } } } @Override public void requestLayout() { if (!mHandlingLayoutInLayoutRequest) { checkThread(); mLayoutRequested = true; scheduleTraversals(); } }
从这两段代码可以看出:
- View的绘制是在onResume()之后调用的
- DecorView之上还有一层View-ViewRootImpl
- 真正的View的测量、摆位、绘制可以说就是在ViewRootImpl的方法setView()中开始的
- layout的刷新方法有requestLayout()
子线程不能更新UI
每一次导致布局刷新的操作都会操作到方法requestLayout(),这里开始了线程的检查;具体看源码:
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
可以看出,当前操作UI的线程不是mThread的话,就会报子线程不能更新UI的操作。mThread是在ViewRootImpl的构造方法调用,该方法的调用链是:
ActivityThread[handleResumeActivity()]-->WindowManagerImpl[addView()]
-->WindowManagerGlobal[addView()]-->ViewRootImpl[构造方法]
即,mThread就是主线程(UI线程)。
View的绘制流程真正开始的地方
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
if (!mUnbufferedInputDispatch) {
scheduleConsumeBatchedInput();
}
notifyRendererOfFramePending();
pokeDrawLockIfNeeded();
}
}
final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
final class TraversalRunnable implements Runnable {
@Override
public void run() {
doTraversal();
}
}
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
if (mProfile) {
Debug.startMethodTracing("ViewAncestor");
}
performTraversals();
if (mProfile) {
Debug.stopMethodTracing();
mProfile = false;
}
}
}
真正的View的绘制流程就从这里performTraversals开始了。
网友评论