带着问题看源码
经过前几篇源码解析文章,我们了解到打开一个新的Activity界面,会执行到Activity的onCreate()方法,然后我们调用setContentView()方法传入希望展示的xml布局,但是我们传入的布局文件时如何展示在手机上的呢?带着这个问题,我们一起深入源码查找解惑
先看Activity的生命周期:
UI绘制入口ActivityThread.handleResumeActivity()
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) { //... //1.创建Activity实例,并调用onCreate()生命周期方法 Activity a = performLaunchActivity(r, customIntent); if (a != null) { r.createdConfig = new Configuration(mConfiguration); reportSizeConfigurations(r); Bundle oldState = r.state; //2.调用onStart()->onResume()生命周期方法 handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason); //... } final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) { //拿到当前Activity保存的数据 ActivityClientRecord r = mActivities.get(token); //... //1.执行Activity的onStart()与onResume()生命周期方法 r = performResumeActivity(token, clearHide, reason); if (r != null) { final Activity a = r.activity; //... boolean willBeVisible = !a.mStartedActivity; if (!willBeVisible) { try { //标示将要进行界面展示 willBeVisible = ActivityManager.getService().willActivityBeVisible( a.getActivityToken()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } if (r.window == null && !a.mFinished && willBeVisible) { //2.下面这段代码主要操作逻辑为 r.window = r.activity.getWindow(); View decor = r.window.getDecorView(); //通过Activity的PhoneWindow拿到DecorView decor.setVisibility(View.INVISIBLE); //先设置DecorView不显示 ViewManager wm = a.getWindowManager(); //通过Activity拿到WindowManager WindowManager.LayoutParams l = r.window.getAttributes(); a.mDecor = decor; l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; if (r.mPreserveWindow) { a.mWindowAdded = true; r.mPreserveWindow = false; ViewRootImpl impl = decor.getViewRootImpl(); if (impl != null) { impl.notifyChildRebuilt(); } } if (a.mVisibleFromClient) { if (!a.mWindowAdded) { a.mWindowAdded = true; //核心方法3.将DecorView添加到WindwoManager中 wm.addView(decor, l); } else { a.onWindowAttributesChanged(l); } } //... if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) { if (r.newConfig != null) { //判断设置的Configureation是否改变了(设备旋转) performConfigurationChangedForActivity(r, r.newConfig); if (DEBUG_CONFIGURATION) Slog.v(TAG, "Resuming activity " + r.activityInfo.name + " with newConfig " + r.activity.mCurrentConfig); r.newConfig = null; } if (localLOGV) Slog.v(TAG, "Resuming " + r + " with isForward=" + isForward); WindowManager.LayoutParams l = r.window.getAttributes(); if ((l.softInputMode & WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != forwardBit) { l.softInputMode = (l.softInputMode & (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)) | forwardBit; if (r.activity.mVisibleFromClient) { //跟新DecorView在Window上的布局展示 ViewManager wm = a.getWindowManager(); View decor = r.window.getDecorView(); wm.updateViewLayout(decor, l); } } r.activity.mVisibleFromServer = true; mNumVisibleActivities++; if (r.activity.mVisibleFromClient) { r.activity.makeVisible(); } } if (!r.onlyLocalRequest) { r.nextIdle = mNewActivities; mNewActivities = r; if (localLOGV) Slog.v( TAG, "Scheduling idle handler for " + r); Looper.myQueue().addIdleHandler(new Idler()); } r.onlyLocalRequest = false; //4.通知AMS该Activity的生命周期onResume执行完毕 if (reallyResume) { try { ActivityManager.getService().activityResumed(token); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } } else { //异常情况,调用界面finish() try { ActivityManager.getService() .finishActivity(token, Activity.RESULT_CANCELED, null, Activity.DONT_FINISH_TASK_WITH_ACTIVITY); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } } }复制代码
将DecorView添加到WindwoManager中wm.addView(decor, l);
找到WindowManager的实现类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); }}其中addView()方法真正的执行者是WindowManagerGlobal复制代码
WindowManagerGlobal.addView()
private final Object mLock = new Object(); private final ArrayListmViews = new ArrayList (); private final ArrayList mRoots = new ArrayList (); private final ArrayList mParams = new ArrayList (); public void addView(View view, ViewGroup.LayoutParams params, Display display, Window parentWindow) { //...各种判断 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; View panelParentView = null; synchronized (mLock) { //先锁住 //... //新建ViewRootImpl实例 root = new ViewRootImpl(view.getContext(), display); view.setLayoutParams(wparams); //缓存,提高性能 //mViews保存的是View对象,DecorView //mRoots保存和顶层View关联的ViewRootImpl对象 //mParams保存的是创建顶层View的layout参数。 mViews.add(view); mRoots.add(root); mParams.add(wparams); //核心方法:调用ViewRootImpl.setView()方法 try { root.setView(view, wparams, panelParentView); } catch (RuntimeException e) { // BadTokenException or InvalidDisplayException, clean up. if (index >= 0) { removeViewLocked(index, true); } throw e; } } }复制代码
核心方法:调用ViewRootImpl.setView()方法
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) { synchronized (this) { if (mView == null) {//只能调用一次 mView = view; //赋值 // ... //1.调用requestLayout() requestLayout(); //... //设置DecorView的parent为ViewRootImpl view.assignParent(this); //... } } } @Override 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); if (!mUnbufferedInputDispatch) { scheduleConsumeBatchedInput(); } notifyRendererOfFramePending(); pokeDrawLockIfNeeded(); } } //执行mTraversalRunnable的run方法 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; } } } private void performTraversals() { // ... if (!mStopped || mReportNextDraw) { boolean focusChangedDueToTouchMode = ensureTouchModeLocally( (relayoutResult&WindowManagerGlobal.RELAYOUT_RES_IN_TOUCH_MODE) != 0); if (focusChangedDueToTouchMode || mWidth != host.getMeasuredWidth() || mHeight != host.getMeasuredHeight() || contentInsetsChanged || updatedConfiguration) { int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width); int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height); if (DEBUG_LAYOUT) Log.v(mTag, "Ooops, something changed! mWidth=" + mWidth + " measuredWidth=" + host.getMeasuredWidth() + " mHeight=" + mHeight + " measuredHeight=" + host.getMeasuredHeight() + " coveredInsetsChanged=" + contentInsetsChanged); // 1.测量 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec); // Implementation of weights from WindowManager.LayoutParams // We just grow the dimensions as needed and re-measure if // needs be int width = host.getMeasuredWidth(); int height = host.getMeasuredHeight(); boolean measureAgain = false; if (lp.horizontalWeight > 0.0f) { width += (int) ((mWidth - width) * lp.horizontalWeight); childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY); measureAgain = true; } if (lp.verticalWeight > 0.0f) { height += (int) ((mHeight - height) * lp.verticalWeight); childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); measureAgain = true; } if (measureAgain) { //再次测量 performMeasure(childWidthMeasureSpec, childHeightMeasureSpec); } layoutRequested = true; } } } else { maybeHandleWindowMove(frame); } final boolean didLayout = layoutRequested && (!mStopped || mReportNextDraw); boolean triggerGlobalLayoutListener = didLayout || mAttachInfo.mRecomputeGlobalAttributes; if (didLayout) { //2.布局 performLayout(lp, mWidth, mHeight); // ... if (!cancelDraw && !newSurface) { if (mPendingTransitions != null && mPendingTransitions.size() > 0) { for (int i = 0; i < mPendingTransitions.size(); ++i) { mPendingTransitions.get(i).startChangingAnimations(); } mPendingTransitions.clear(); } //3.绘制 performDraw(); } else { if (isViewVisible) { // Try again scheduleTraversals(); } else if (mPendingTransitions != null && mPendingTransitions.size() > 0) { for (int i = 0; i < mPendingTransitions.size(); ++i) { mPendingTransitions.get(i).endChangingAnimations(); } mPendingTransitions.clear(); } } mIsInTraversal = false; }复制代码
在performTraversals()方法中,执行测量performMeasure(),布局performLayout(),绘制performDraw(),这三个方法最终都会调用View的相对应方法 UML调用时序图: