Android startActivity流程分析(二) onCreate,onStart,onResume Android 10 [API 29]

接着Android startActivity流程分析(一) Android 10 [API 29] 中的Activity#attach完成后。

startActivity还包含onCreate、onStart、onResume,逐一分析。

image.png

onCreate()

Activity#onCreate中主要是进行Create事件的回调,包括FragmentManager及ActivityLifecycleCallbacks

protected void onCreate(@Nullable Bundle savedInstanceState) {
        ....
        mFragments.dispatchCreate();
        dispatchActivityCreated(savedInstanceState);
        ...
        mCalled = true;
    }

Activity#setContentView

public void setContentView(@LayoutRes int layoutResID) {
    getWindow().setContentView(layoutResID);
    initWindowDecorActionBar();
}

这里getWindow()返回的是PhoneWindow对象,进入PhoneWindow的setContentView其中主要为以下2项

  1. installDecor(),初始化DecorView,同时mContentParent也被赋值
  2. mLayoutInflater.inflate(layoutResID, mContentParent);构建View

注:使用appcompat下的AppCompatActivity后流程会有差异,但整体逻辑差别不大

PhoneWindow.java
  
public void setContentView(int layoutResID) {
    if (mContentParent == null) {
        installDecor();
    } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
        mContentParent.removeAllViews();
    }
    ....
        mLayoutInflater.inflate(layoutResID, mContentParent);
    ....
    mContentParent.requestApplyInsets();
  // Activity#attach时,mWindow.setCallback(this),所以此处调用的为Activity#onContentChanged
    final Callback cb = getCallback();
    if (cb != null && !isDestroyed()) {
        cb.onContentChanged();
    }
    mContentParentExplicitlySet = true;
}
PhoneWindow#installDecor

构建了DecorView,并初始化mContentParent,mContentParent的id为ID_ANDROID_CONTENT

ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);

检查是否有title,有的话是否要隐藏。

private void installDecor() {
    mForceDecorInstall = false;
    if (mDecor == null) {
        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) {
        mContentParent = generateLayout(mDecor);
        // Set up decor part of UI to ignore fitsSystemWindows if appropriate.
        mDecor.makeOptionalFitsSystemWindows();
        ....
          //初始化title
            mTitleView = findViewById(R.id.title);
            if (mTitleView != null) {
              // 查看mLocalFeatures的第FEATURE_NO_TITLE位是否为1,为0的话隐藏titleContainer
                if ((getLocalFeatures() & (1 << FEATURE_NO_TITLE)) != 0) {
                    final View titleContainer = findViewById(R.id.title_container);
                    if (titleContainer != null) {
                        titleContainer.setVisibility(View.GONE);
                    } else {
                        mTitleView.setVisibility(View.GONE);
                    }
                    mContentParent.setForeground(null);
                } else {
                    mTitleView.setText(mTitle);
                }
            }
        }
        ....
    }
}
LayoutInflater.inflate()

mLayoutInflater.inflate(layoutResID, mContentParent); 这里用到了两个参数的重载,即Inflate指定的layout并添加到mContentParent中。

onStart()

第二步:performLifecycleSequence,其中计算start、finish之间的状态,并调用ActivityThread的handleStartActivity

TransactionExecutor.java
  
private void cycleToPath(ActivityClientRecord r, int finish, boolean excludeLastState,
            ClientTransaction transaction) {
        final int start = r.getLifecycleState();
        ....
          //这里start为1:ON_CREATE,finish为3:ON_RESUME计算后path中包含2:ON_START
        final IntArray path = mHelper.getLifecyclePath(start, finish, excludeLastState);
        performLifecycleSequence(r, path, transaction);
    }
​
private void performLifecycleSequence(ActivityClientRecord r, IntArray path,
            ClientTransaction transaction) {
        final int size = path.size();
        for (int i = 0, state; i < size; i++) {
            state = path.get(i);
            ......
            switch (state) {
                case ON_CREATE:
                    mTransactionHandler.handleLaunchActivity(r, mPendingActions,
                            null /* customIntent */);
                    break;
                case ON_START:
                //调用ActivityThread的handleStartActivity
                    mTransactionHandler.handleStartActivity(r, mPendingActions);
                    break;
                case ON_RESUME:
                    mTransactionHandler.handleResumeActivity(r.token, false /* finalStateRequest */,
                            r.isForward, "LIFECYCLER_RESUME_ACTIVITY");
                    break;
                .......
    }

ActivityThread#handleStartActivity中开始Activity的start

ActivityThread.java
  
public void handleStartActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions) {
        final Activity activity = r.activity;
        .....
        // Start
        activity.performStart("handleStartActivity");
        r.setState(ON_START);
        .....
    }

后续执行Activity#performStart并通过Instrumentation调用activity的onStart完成start流程。

onResume()

在TransactionExecutor的第三步,也就是lifecycleItem.execute,即执行ResumeActivityItem的execute。进入了ActivityThread的handleResumeActivity

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

handleResumeActivity中

1.调用了Activity的performResume通过Instrumentation#callActivityOnResume回调Activity的onResume。并更新ActivityClientRecord的state为ON_RESUME

2.将Window中的DecorView赋值给Activity的成员变量mDecor,通过WindowManagerGlobal#addView将DecorView加入到WMS中。

ActivityThread.java
  
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
            String reason) {
        ....
        // TODO Push resumeArgs into the activity for consideration
        final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
        ......
        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;
            ......
            if (a.mVisibleFromClient) {
                if (!a.mWindowAdded) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                } else {
             .....
        }
        .....
    }

WindowManagerImpl#addView流程

其中较为重要的有三点:

  1. 创建ViewRootImpl

    其中有个细节是会对成员变量mThread赋值为当前线程,也就是主线程,后续其中的方法调用大多都会调用checkThread检查从哪个线程来的,若不是主线程则会抛出异常。

    ViewRootImpl.java
    public ViewRootImpl(Context context, Display display) {
      mThread = Thread.currentThread();
    }
    ​
    void checkThread() {
            if (mThread != Thread.currentThread()) {
                throw new CalledFromWrongThreadException(
                        "Only the original thread that created a view hierarchy can touch its views.");
            }
        }
    
  2. 构建DecorView、ViewRootImpl、WindowManager.LayoutParams的对应关系

  3. 添加到WMS并显示

ViewManager对象wm是通过a.getWindowManager()得到的,其初始化参考attach流程。wm.addView(decor, l);调用的为

WindowManagerImpl#addView() -> WindowManagerGlobal.addView()

WindowManagerGlobal是App侧的单例,其中mViews、mRoots、mParams分别保存着App内的所有DecorView及与之对应的ViewRootImpl、WindowManager.LayoutParams。

WindowManagerGlobal.java
  
public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow) {
    ......
    ViewRootImpl root;
    View panelParentView = null;
​
    synchronized (mLock) {
        ....
        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 {
            root.setView(view, wparams, panelParentView);
        .......
    }
}

添加完后进入ViewRootImpl#setView

ViewRootImpl.java
  
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();
            ....
                res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
                        getHostVisibility(), mDisplay.getDisplayId(), mTmpFrame,
                        mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
                        mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel,
                        mTempInsets);
                setFrame(mTmpFrame);
            .....
    }
}

其中主要做了两件事

  1. requestLayout()

    检查线程,标记状态后进入scheduleTraversals()

    public void requestLayout() {
        if (!mHandlingLayoutInLayoutRequest) {
            checkThread();
            mLayoutRequested = true;
            scheduleTraversals();
        }
    }
    

    scheduleTraversals()

    1. 添加同步屏障
    2. mChoreographer.postCallback,将mTraversalRunnable加入到Choreographer类的mCallbackQueues中
    void scheduleTraversals() {
        if (!mTraversalScheduled) {
            mTraversalScheduled = true;
            mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
            mChoreographer.postCallback(
                    Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
            .......
        }
    }
    

    下一个VSync脉冲到来回调FrameDisplayEventReceiver#onVsync后进入Choreographer的doFrame,在其中调用doCallbacks执行所有类型为Choreographer.CALLBACK_TRAVERSAL的callback,即ViewRootImpl中的TraversalRunnable

    void doFrame(long frameTimeNanos, int frame) {
        .....
        try {
            .....
            mFrameInfo.markPerformTraversalsStart();
            doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
            doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
        } finally {
            AnimationUtils.unlockAnimationClock();
            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
        }
        ....
    }
    

    ViewRootImpl.TraversalRunnable

    final class TraversalRunnable implements Runnable {
        @Override
        public void run() {
            doTraversal();
        }
    }
    

    ViewRootImpl#doTraversal()

    其中包含两步

    1.removeSyncBarrier清除内存屏障让所有消息都得以执行

    2.performTraversals

    void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
          ......
            performTraversals();
          ......
        }
    }
    

    ViewRootImpl#performTraversals

    performTraversals中包含了对View及其子View的Measure、Layout、Draw操作,View完成展示。

    private void performTraversals() {
        .....
            performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
          ....
            performLayout(lp, mWidth, mHeight);
         .....
            performDraw();
        .....
    ​
        mIsInTraversal = false;
    }
    
  2. mWindowSession.addToDisplay 这里的mWindowSession是通过WindowManagerGlobal.getWindowSession()赋值的,其实现为server下的Session类

    public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
            int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
            Rect outStableInsets, Rect outOutsets,
            DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel,
            InsetsState outInsetsState) {
        return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
                outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel,
                outInsetsState);
    }
    

    最终调用的是WMS的addWindow进行添加

总结

onCreate过程中创建了DecorView并解析传入的布局文件添加到DecorView。

onStart回调在Activity对用户可见时,前后台切换场景的逻辑较多在此处理。

onResume中包括

  1. 将Activity中的mDecor与Window中decor关联
  2. WindowManagerGlobal中建立ViewRootImpl、DecorView、WindowManager.LayoutParams的关联
  3. 调用ViewRootImpl#setView,将ViewRootImpl包装为IWindow添加到WMS中,并调用requestLayout显示UI

猜你喜欢

转载自juejin.im/post/7116793363495403551