androidP: View的工作原理-初识ViewRoot和DecorView

参考链接:
Activity、Window、DecorView与ViewRoot之间的关系 :
https://blog.csdn.net/m0_37698652/article/details/101381021?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_paycolumn_v3&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1.pc_relevant_paycolumn_v3&utm_relevant_index=1
在这里插入图片描述
**Activity:**负责控制生命周期和处理事件,负责统筹视图的添加与显示,以及通过一些回调方法与Window和View进行交互。一个Activity包含一个Window,真正控制视图的是Window,Window才是真正代表一个窗口。

**Window:**是视图的承载者,是一个抽象类,Activity中持有的实际上是Window的子类PhoneWindow,Window通过WindowManager加载了一个DecorView到Window中,并将DecorView交给了ViewRoot。

**DecorView:**是FrameLayout的子类,它可以被认为是Android视图树的根节点视图,是setContentView所设置的View的父容器,一般情况下它内部包含了一个竖直方向的LinearLayout,在这个LinearLayout中有三个部分,上面是ViewStub,延迟加载的视图(设置ActionBar),中间是标题栏TittleView(根据Theme是否显示),下面是内容栏ContentView。

**ViewRoot:**对应ViewRootImp类,它是连接WindowManager和DecorView的纽带,在ActivityThread中,当Activity对象创建完毕后,会将DecorView添加到Window中,同时会创建ViewRootImp对象,并将ViewRootImp对象和DecorView建立关联。View的三大流程measure layout draw都是通过ViewRoot完成。ViewRoot并不属于View树的一部分,从源码上看它既非View的子类,也非View的父类,但是它实现了ViewParent接口,所以可以算作名义上的View的父视图。ViewRoot继承了Handler类,Android所有的触屏事件、按键事件、界面刷新等事件都是通过ViewRoot进行分发的。

android代码中新建Activity后,要在onCreate()重写方法中使用setContentView(R.layout.xxx)方法加载activity的布局,即调用Activity.setContentView()方法。

android_build_9/frameworks/base/core/java/android/app/Activity.java
private Window mWindow;
public void setContentView(@LayoutRes int layoutResID) {
        getWindow().setContentView(layoutResID);
        initWindowDecorActionBar();
}

 public Window getWindow() {
        return mWindow;
 }

在setContentView 方法中调用了getWindow()返回Window实例mWindow。mWindow实例的获取是在Activity.attach()方法中,同时设置了WindowManager服务。

private WindowManager mWindowManager;
/** Retrieve the window manager for showing custom windows. */
public WindowManager getWindowManager() {
      return mWindowManager;
}

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*/);
        
        //获取window实例,实际持有的是window子类PhoneWindow的实例。
        mWindow = new PhoneWindow(this, window, activityConfigCallback);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
        mWindow.getLayoutInflater().setPrivateFactory(this);
        if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
            mWindow.setSoftInputMode(info.softInputMode);
        }
        if (info.uiOptions != 0) {
            mWindow.setUiOptions(info.uiOptions);
        }
        mUiThread = Thread.currentThread();

        mMainThread = aThread;
        mInstrumentation = instr;
        mToken = token;
        mIdent = ident;
        mApplication = application;
        mIntent = intent;
        mReferrer = referrer;
        mComponent = intent.getComponent();
        mActivityInfo = info;
        mTitle = title;
        mParent = parent;
        mEmbeddedID = id;
        mLastNonConfigurationInstances = lastNonConfigurationInstances;
        if (voiceInteractor != null) {
            if (lastNonConfigurationInstances != null) {
                mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
            } else {
                mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
                        Looper.myLooper());
            }
        }
       
        //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());
        }
        mWindowManager = mWindow.getWindowManager();
        mCurrentConfig = config;

        mWindow.setColorMode(info.colorMode);

        setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
        enableAutofillCompatibilityIfNeeded();
    }

经过以上,实际调用PhoneWindow类中setContentView()方法:

//Window是抽象类,PhoneWindow继承Window
android_build_9/frameworks/base/core/java/android/view/Window.java
android_build_9/frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
@Override
    public void setContentView(int layoutResID) {
        // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
        // decor, when theme attributes and the like are crystalized. Do not check the feature
        // before this happens.
        if (mContentParent == null) {
            installDecor(); //创建DecorView
        } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            mContentParent.removeAllViews();
        }
        
        //创建好DecorView后,将activty的布局添加到DecorView
        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }
        mContentParent.requestApplyInsets();
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
        mContentParentExplicitlySet = true;
    }

mContentParent就是ContentView所对应的的FrameLayout。当mContentParent为空时,通过installDecor创建DecorView。

private void installDecor() {
    mForceDecorInstall = false;
        if (mDecor == null) {
            //生成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) {
            // 为DecorView设置布局格式,并返回mContentParent
            mContentParent = generateLayout(mDecor);
            ......
        }
        ......
}

//创建DecorView
 protected DecorView generateDecor(int featureId) {
        // System process doesn't have application context and in that case we need to directly use
        // the context we have. Otherwise we want the application context, so we don't cling to the
        // activity.
        Context context;
        if (mUseDecorContext) {
            Context applicationContext = getContext().getApplicationContext();
            if (applicationContext == null) {
                context = getContext();
            } else {
                context = new DecorContext(applicationContext, getContext());
                if (mTheme != -1) {
                    context.setTheme(mTheme);
                }
            }
        } else {
            context = getContext();
        }
        //生成DecorView
        return new DecorView(context, featureId, this, getAttributes());
    }
    
    //生成DecorView布局文件
     protected ViewGroup generateLayout(DecorView decor) {
        // Apply data from current theme.从主题文件中获取样式信息
        TypedArray a = getWindowStyle();
        ...
        if (a.getBoolean(R.styleable.Window_windowNoTitle, false)) {
            requestFeature(FEATURE_NO_TITLE);
        } else if (a.getBoolean(R.styleable.Window_windowActionBar, false)) {
            // Don't allow an action bar if there is no title.
            requestFeature(FEATURE_ACTION_BAR);
        }
        ...
        // Inflate the window decor.
        int layoutResource;
         根据主题样式,加载窗口布局
        int features = getLocalFeatures();
        // System.out.println("Features: 0x" + Integer.toHexString(features));
        if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
            layoutResource = R.layout.screen_swipe_dismiss;
            setCloseOnSwipeEnabled(true);
        } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
            ....
        }
        ...
        mDecor.startChanging();
        mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
        ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
        ...
        //返回DecorView的布局文件
        return contentParent;
     }

先从主题中获取样式,然后根据样式,加载对应的布局到DecorView中,然后从中获取mContentParent。获得到之后,可以回到上面的代码,为mContentParent添加View,即Activity中的布局。

 //创建好DecorView后,将activty的布局添加到DecorView
        if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
            final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID,
                    getContext());
            transitionTo(newScene);
        } else {
            mLayoutInflater.inflate(layoutResID, mContentParent);
        }

onCreate()方法执行->加载activity布局完成:
在这里插入图片描述
以上仅仅是将DecorView建立起来,通过setContentView设置的界面,如何在onResume后对用户可见。

(注:handleResumeActivity()方法调用流程后面补充)
在TransactionExecutor类execute方法中依次执行executeCallbacks()和executeLifecycleState()方法,当executeCallbacks方法执行完毕后,activity的生命周期到onCreate,并且成功加载完activity.xml布局。执行executeLifecycleState()方法进行activity的后面生命周期onResume。

// android_build_9/frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);

        executeCallbacks(transaction);

        executeLifecycleState(transaction);
        mPendingActions.clear();
        log("End resolving transaction");
    }

/** Transition to the final state if requested by the transaction. */
private void executeLifecycleState(ClientTransaction transaction) {
     //这里获取到的lifecycleItem为ResumeActivityItem
     final ActivityLifecycleItem lifecycleItem = transaction.getLifecycleStateRequest();
     ...
     // Execute the final transition with proper parameters.
     lifecycleItem.execute(mTransactionHandler, token, mPendingActions);
     lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions); 
     ...
}

android_build_9/frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
 /** Get the target state lifecycle request. */
    @VisibleForTesting
    public ActivityLifecycleItem getLifecycleStateRequest() {
        return mLifecycleStateRequest;
    }
   /**
     * Set the lifecycle state in which the client should be after executing the transaction.
     * @param stateRequest A lifecycle request initialized with right parameters.
     */
    public void setLifecycleStateRequest(ActivityLifecycleItem stateRequest) {
        mLifecycleStateRequest = stateRequest;
    }

在onCreate()流程中,ActivityStackSupervisor类中realStartActivityLocked()方法实现添加下一个生命周期方法:

/android_build_9/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig)     throws RemoteException {
     final ActivityManagerService mService;
     ...
     // Create activity launch transaction.
     final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread, r.appToken);
     clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                        profilerInfo));
       // Set desired final state.
       final ActivityLifecycleItem lifecycleItem;
       if (andResume) { //andResume值为true
             lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward()); 
       } else {
             lifecycleItem = PauseActivityItem.obtain();
       }
      //将ResumeActivityItem(activity的下一个状态)设置给clientTransaction
      clientTransaction.setLifecycleStateRequest(lifecycleItem);
       // Schedule transaction.
      mService.getLifecycleManager().scheduleTransaction(clientTransaction);
    ...
}
// android_build_9/frameworks/base/core/java/android/app/servertransaction/ResumeActivityItem.java
@Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
        client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
                "RESUME_ACTIVITY");
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
/android_build_9/frameworks/base/core/java/android/app/ActivityThread.java
@Override
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
     // If we are getting ready to gc after going to the background, well
        // we are back active so skip it.
        unscheduleGcIdler();
        mSomeActivitiesChanged = true;

        // TODO Push resumeArgs into the activity for consideration
        //这个时候,Activity.onResume()已经调用了,但是现在界面还是不可见的
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
        if (r == null) {
            // We didn't actually resume the activity, so skipping any follow-up actions.
            return;
        }

        final Activity a = r.activity;

        if (localLOGV) {
            Slog.v(TAG, "Resume " + r + " started activity: " + a.mStartedActivity
                    + ", hideForNow: " + r.hideForNow + ", finished: " + a.mFinished);
        }

        final int forwardBit = isForward
                ? WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION : 0;

        // If the window hasn't yet been added to the window manager,
        // and this guy didn't finish itself or start another activity,
        // then go ahead and add the window.
        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) {
            r.window = r.activity.getWindow();
            View decor = r.window.getDecorView();
            //decor对用户不可见
            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 (r.mPreserveWindow) {
                a.mWindowAdded = true;
                r.mPreserveWindow = false;
                // Normally the ViewRoot sets up callbacks with the Activity
                // in addView->ViewRootImpl#setView. If we are instead reusing
                // the decor view we have to notify the view root that the
                // callbacks may have changed.
                ViewRootImpl impl = decor.getViewRootImpl();
                if (impl != null) {
                    impl.notifyChildRebuilt();
                }
            }
            if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;
                    //被添加进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);
                }
            }

            // If the window has already been added, but during resume
            // we started another activity, then don't yet make the
            // window visible.
        } else if (!willBeVisible) {
            if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
            r.hideForNow = true;
        }

        // Get rid of anything left hanging around.
        cleanUpPendingRemoveWindows(r, false /* force */);

        // 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) {
            if (r.newConfig != null) {
                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) {
                    ViewManager wm = a.getWindowManager();
                    View decor = r.window.getDecorView();
                    wm.updateViewLayout(decor, l);
                }
            }

            r.activity.mVisibleFromServer = true;
            mNumVisibleActivities++;
            //在这里,执行了重要的操作,使得DecorView可见
            if (r.activity.mVisibleFromClient) {
                r.activity.makeVisible();
            }
        }

        r.nextIdle = mNewActivities;
        mNewActivities = r;
        if (localLOGV) Slog.v(TAG, "Scheduling idle handler for " + r);
        Looper.myQueue().addIdleHandler(new Idler());
}

// android_build_9/frameworks/base/core/java/android/app/Activity.java
void makeVisible() {
        if (!mWindowAdded) {
            ViewManager wm = getWindowManager();
            wm.addView(mDecor, getWindow().getAttributes());
            mWindowAdded = true;
        }
        mDecor.setVisibility(View.VISIBLE);
}

到此DecorView便可见,显示在屏幕中。但是在这其中,wm.addView(mDecor, getWindow().getAttributes());起到了重要的作用,因为其内部创建了一个ViewRootImpl对象,负责绘制显示各个子View。具体来看addView()方法,因为WindowManager是个接口,具体是交给WindowManagerImpl来实现的。

android_build_9/frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
/android_build_9/frameworks/base/core/java/android/app/ClientTransactionHandler.java
android_build_9/frameworks/base/core/java/android/app/servertransaction/ActivityLifecycleItem.java
android_build_9/frameworks/base/core/java/android/app/servertransaction/ClientTransactionItem.java
android_build_9/frameworks/base/services/core/java/com/android/server/am/ClientLifecycleManager.java
/android_build_9/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

android_build_9/frameworks/base/core/java/com/android/internal/policy/DecorView.java
android_build_9/frameworks/base/core/java/android/view/WindowManagerImpl.java
@Override
    public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
        applyDefaultToken(params);
        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
    }

android_build_9/frameworks/base/core/java/android/view/WindowManagerGlobal.java
public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        ...
        final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
        ...    
        ViewRootImpl root;
        synchronized (mLock) {
           ...
            //实例化一个ViewRootImpl对象
            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 {
            //将DecorView交给ViewRootImpl
                root.setView(view, wparams, panelParentView);
            } catch (RuntimeException e) {
              ...
                throw e;
            }
        }
}

// android_build_9/frameworks/base/core/java/android/view/ViewRootImpl.java
/**
     * We have one child
*/
//params:view = DecorVIew
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
     ...
     // 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();
   }
}

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;
            }
        }
 }

在这里插入图片描述

// android_build_9/frameworks/base/core/java/android/view/ViewRootImpl.java
public ViewRootImpl(Context context, Display display) {
    ...
    mFirst = true; // true for the first time the view is added
    ...
}
public final WindowManager.LayoutParams mWindowAttributes = new WindowManager.LayoutParams();
final Rect mWinFrame; // frame given by window manager.
mWinFrame = mWinFrame = new Rect();
private void performTraversals() {
  // cache mView since it is used so much below...
  //mView就是DecorView根布局,记录ViewRootImpl管理的View树的根节点,final修饰,避免运行过程中修改
  final View host = mView;
  ...
  判断View绘制的条件是否具备.mAdded是DecorView是否成功添加到,Window的标示位,如果一切顺利的话,这里应该为ture,因此不会return.
  if (host == null || !mAdded)
      return;
  //是否正在遍历
  mIsInTraversal = true;
  //是否马上绘制View
  mWillDrawSoon = true;
  //视图的大小可能改变
  boolean windowSizeMayChange = false;
  //新界面
  boolean newSurface = false;
  //界面改变
  boolean surfaceChanged = false;
  WindowManager.LayoutParams lp = mWindowAttributes;
  //顶层视图DecorView所需要窗口的宽度和高度
  int desiredWindowWidth;
  int desiredWindowHeight;   
  //DecorView视图是否可见
  final int viewVisibility = getHostVisibility();
  //视图可见性改变
  final boolean viewVisibilityChanged = !mFirst
                && (mViewVisibility != viewVisibility || mNewSurfaceNeeded
                // Also check for possible double visibility update, which will make current
                // viewVisibility value equal to mViewVisibility and we may miss it.
                || mAppVisibilityChanged);
   ...
   //将一个全局的Rect对象赋给了局部frame对象,它用来保存Activity窗口当前的宽度和高度
   Rect frame = mWinFrame;
    /*============================这段代码中主要交代了Activity当前的Window的宽高是如何得出的========*/
   //在构造方法中mFirst已经设置为true,表示是否是第一次被请求执行测量、布局和绘制操作,
   if (mFirst) {
       mFullRedrawNeeded = true;       //是否需要全部重绘
       mLayoutRequested = true;        //是否要求重新Layout界面
       final Configuration config = mContext.getResources().getConfiguration();
       //如果窗口的类型是有状态栏的,那么Activity窗口的宽度和高度就是除了状态栏
       if (shouldUseDisplaySize(lp)) {
                // NOTE -- system code, won't try to do compat mode.
                Point size = new Point();
                mDisplay.getRealSize(size);
                desiredWindowWidth = size.x;
                desiredWindowHeight = size.y;
            } else {//否则Activity窗口的宽度和高度就是整个屏幕的宽高
                desiredWindowWidth = mWinFrame.width();
                desiredWindowHeight = mWinFrame.height();
      }
      ...
   }else {
           //除了第一次被请求执行测量、布局和绘制操作以外,它的当前宽度desiredWindowWidth和高度
           //就等于保存在ViewRootImpl类的成员变量mWinFrame/frame中的宽度和高度值,也就是上一次储存的宽高值.
            desiredWindowWidth = frame.width();//以改变后的参数来绘制DecorView的宽高
            desiredWindowHeight = frame.height();
            if (desiredWindowWidth != mWidth || desiredWindowHeight != mHeight) {
                if (DEBUG_ORIENTATION) Log.v(mTag, "View " + host + " resized to: " + frame);
               // mWidth此时代表的是上一次执行该方法的时候的frame.width()值,如果此时两值不相等,那就说明视图改变需要重新测量绘制了。
                mFullRedrawNeeded = true;//需要重新绘制标志位
                mLayoutRequested = true;//要求重新Layout标志位
                windowSizeMayChange = true;//Window的尺寸可能改变
   } 
   /*============================这段代码中主要交代了Activity当前的Window的宽高是如何得出的========*/
 }
  ...
  // Ask host how big it wants to be
  int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
  int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
  //对decorView执行performMeasure;
  performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
  ...
  performLayout(lp, mWidth, mHeight);
  ...
  performDraw();
  ...
  
  private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
        if (mView == null) {
            return;
        }
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
        try {
            //开始执行View类中measur->onMeasure
            mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
    }
  
}

private void performLayout(WindowManager.LayoutParams lp, int desiredWindowWidth,int desiredWindowHeight) {
     ...
     host.layout(0, 0, host.getMeasuredWidth(), host.getMeasuredHeight());
     ...
}

 private void performDraw() {
    boolean canUseAsync = draw(fullRedrawNeeded);
 }

private static boolean shouldUseDisplaySize(final WindowManager.LayoutParams lp) {
        return lp.type == TYPE_STATUS_BAR_PANEL
                || lp.type == TYPE_INPUT_METHOD
                || lp.type == TYPE_VOLUME_OVERLAY;
}

 private boolean draw(boolean fullRedrawNeeded) {
      if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset,
                        scalingRequired, dirty, surfaceInsets)) {
           return false;
      }
}
/**
     * @return true if drawing was successful, false if an error occurred
     */
    private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff,
            boolean scalingRequired, Rect dirty, Rect surfaceInsets) {
     mView.draw(canvas);   
}

// android_build_9/frameworks/base/core/java/android/view/View.java

以上是performTraversals开始绘制view得大体流程。怎样从decorView到activity 每一个子view绘制过程,还是没看懂,performTraversals得细节看下面制片文章。https://www.jianshu.com/p/a65861e946cb View绘制流程及源码解析(一)——performTraversals()源码分析(太难了。)
其实ViewRootImpl的作用不止如此,还有许多功能,如事件分发。.
当用户点击屏幕产生一个触摸行为,这个触摸行为则是通过底层硬件来传递捕获,然后交给ViewRootImpl,接着将事件传递给DecorView,而DecorView再交给PhoneWindow,PhoneWindow再交给Activity,然后接下来就是我们常见的View事件分发了。
硬件 -> ViewRootImpl -> DecorView -> PhoneWindow -> Activity

在这里插入图片描述
补充:从ActivityThread.main()函数开始->onCreate()方法执行
在这里插入图片描述
在这里插入图片描述

/android_build_9/frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
    ...
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);
    ...
}

 private void attach(boolean system, long startSeq) {
     ...
     final IActivityManager mgr = ActivityManager.getService();
     try {
          mgr.attachApplication(mAppThread, startSeq);
     } catch (RemoteException ex) {
          throw ex.rethrowFromSystemServer();
     }
     ...
 }

// android_build_9/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
final ActivityStackSupervisor mStackSupervisor;
@GuardedBy("this")
private final boolean attachApplicationLocked(IApplicationThread thread,int pid, int callingUid, long startSeq) {
    ...
    // See if the top visible activity is waiting to run in this process...
        if (normalMode) {
            try {
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
    ...
}

// android_build_9/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    ...
    for (int i = 0; i < size; i++) {
                    final ActivityRecord activity = mTmpActivityList.get(i);
                    if (activity.app == null && app.uid == activity.info.applicationInfo.uid
                            && processName.equals(activity.processName)) {
                        try {
                            if (realStartActivityLocked(activity, app,
                                    top == activity /* andResume */, true /* checkConfig */)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                            Slog.w(TAG, "Exception in new application when starting activity "
                                    + top.intent.getComponent().flattenToShortString(), e);
                            throw e;
                        }
                    }
                }
   ...
}

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig)     throws RemoteException {
     final ActivityManagerService mService;
     ...
     // Create activity launch transaction.
     final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread, r.appToken);
     clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,
                        // TODO: Have this take the merged configuration instead of separate global
                        // and override configs.
                        mergedConfiguration.getGlobalConfiguration(),
                        mergedConfiguration.getOverrideConfiguration(), r.compat,
                        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
                        r.persistentState, results, newIntents, mService.isNextTransitionForward(),
                        profilerInfo));
       // Set desired final state.
       final ActivityLifecycleItem lifecycleItem;
       if (andResume) { //andResume值为true
             lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward()); 
       } else {
             lifecycleItem = PauseActivityItem.obtain();
       }
      //将ResumeActivityItem(activity的下一个状态)设置给clientTransaction
      clientTransaction.setLifecycleStateRequest(lifecycleItem);
       // Schedule transaction.
      mService.getLifecycleManager().scheduleTransaction(clientTransaction);
    ...
}

// android_build_9/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
ClientLifecycleManager getLifecycleManager() {
        return mLifecycleManager;
}


//android_build_9/frameworks/base/services/core/java/com/android/server/am/ClientLifecycleManager.java
 void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
        final IApplicationThread client = transaction.getClient();
        transaction.schedule();
        if (!(client instanceof Binder)) {
            // If client is not an instance of Binder - it's a remote call and at this point it is
            // safe to recycle the object. All objects used for local calls will be recycled after
            // the transaction is executed on client in ActivityThread.
            transaction.recycle();
        }
 }
 
 // android_build_9/frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
 /** Target client. */
private IApplicationThread mClient;
public void schedule() throws RemoteException {
        mClient.scheduleTransaction(this);
}

在realStartActivityLocked()方法中,会创建一个 ClientTransaction 对象,并给 ClientTransaction 实例添加 LaunchActivityItem 形式的 CallBack 和设置 setLifecycleStateRequest。通过ActivityManagerService.getLifecycleManager().scheduleTransaction(clientTransaction)将ClientTransaction 实例传递到客户线程(ActivityThread)。IApplicationThread 的实现类为ApplicationThread,为ActivtyThread的内部类。

// android_build_9/frameworks/base/core/java/android/app/ActivityThread.java
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
   ActivityThread.this.scheduleTransaction(transaction);
}

ActivityThread继承ClientTransactionHandler类,因此看ClientTransactionHandler类中scheduleTransaction()方法的实现

// android_build_9/frameworks/base/core/java/android/app/ClientTransactionHandler.java
/** Prepare and schedule transaction for execution. */
void scheduleTransaction(ClientTransaction transaction) {
     transaction.preExecute(this);
     sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
}

// android_build_9/frameworks/base/core/java/android/app/ActivityThread.java
public static final int EXECUTE_TRANSACTION = 159;
public void handleMessage(Message msg) {
    case EXECUTE_TRANSACTION:
         final ClientTransaction transaction = (ClientTransaction) msg.obj;
         mTransactionExecutor.execute(transaction);
         if (isSystem()) {
             // Client transactions inside system process are recycled on the client side
             // instead of ClientLifecycleManager to avoid being cleared before this
             // message is handled.
             transaction.recycle();
         }
       // TODO(lifecycler): Recycle locally scheduled transactions.
      break;
}

// android_build_9/frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) {
        final IBinder token = transaction.getActivityToken();
        log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);

        executeCallbacks(transaction);

        executeLifecycleState(transaction);
        mPendingActions.clear();
        log("End resolving transaction");
}

@VisibleForTesting
 public void executeCallbacks(ClientTransaction transaction) {
    final List<ClientTransactionItem> callbacks = transaction.getCallbacks();
    final int size = callbacks.size();
    for (int i = 0; i < size; ++i) {
        final ClientTransactionItem item = callbacks.get(i);
        item.execute(mTransactionHandler, token, mPendingActions);
        item.postExecute(mTransactionHandler, token, mPendingActions);
    }
 }

还记着上面有ClientTransaction 实力add LaunchActivityItem的callBack嘛,这里取出LaunchActivityItem的callback,并执行execute()方法。其中LaunchActivityItem类继承ClientTransactionItem类

// android_build_9/frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java
@Override
    public void execute(ClientTransactionHandler client, IBinder token,
            PendingTransactionActions pendingActions) {
        Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
        ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
                mPendingResults, mPendingNewIntents, mIsForward,
                mProfilerInfo, client);
        client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }

//ClientTransactionHandler 是ActivityThread的父类
// android_build_9/frameworks/base/core/java/android/app/ActivityThread.java
 @Override
 public Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {
     ...
     final Activity a = performLaunchActivity(r, customIntent);
     ...
 }

/**  Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    Activity activity = null;
     try {
            java.lang.ClassLoader cl = appContext.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }
...
activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor, window, r.configCallback);
...
mInstrumentation.callActivityOnCreate(activity, r.state);
...
}

到此,终于调用到Activty.attch方法,通过attach方法获取Window实例,WindowManager服务,开始actvity的装载。
后面会学习,ActivityThread的启动流程。下面是新知识点:

Android系统升级到P,它重构了H类,把100到109这10个用于Activity的消息,都合并为159这个消息,消息名为EXECUTE_TRANSACTION。修改原因:Activity的生命周期其实是一个由Create、Pause、Resume、Stop、Destory、Restart组成的状态机。按照设计模式中状态模式的定义,可以把每个状态都定义成一个类,于是便有了如下的类图:

相关源码路径:
android_build_9/frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java
在这里插入图片描述
就拿LaunchActivity来说吧,在Android P之前,是在H类的handleMessage方法的switch分支语句中,编写启动一个Activity的逻辑:

 public void handleMessage(Message msg) {
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
                } break;
            
            //以下省略很多代码
            }
        }

在Android P中,启动Activity的这部分逻辑,被转移到了LaunchActivityItem类的execute方法中。
从架构的角度来说,这次重构的效果很好。使用状态模式,使得Android这部分代码,就是OOP的了。我们把写在H类的handleMessage方法中的switch分支语句,拆分到很多类中,这就符合了五大设计原则中的开闭原则,宁肯有100个类,每个类有100行代码,也不要有一个一万行代码的类。好处是,当我想改动Resume这个状态的业务逻辑时,我只要在ResumeActivityItem类中修改并进行测试就可以了,影响的范围很小。但是这次重构也有缺点,OOP的缺点就是代码会让人看不懂,因为只有在运行时才知道到底实例化的是哪个类,这让原本清晰的Android Activity消息逻辑变得支离破碎。按照这个趋势,四大组件之一的Service,它在H类中也有很多消息,也是有很多生命周期函数,Android的下个版本,极有可能把Service也重构为状态模式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值