接着Android startActivity流程分析(一) Android 10 [API 29] 中的Activity#attach完成后。
startActivity还包含onCreate、onStart、onResume,逐一分析。
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项
- installDecor(),初始化DecorView,同时mContentParent也被赋值
- 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流程
其中较为重要的有三点:
-
创建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."); } }
-
构建DecorView、ViewRootImpl、WindowManager.LayoutParams的对应关系
-
添加到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);
.....
}
}
其中主要做了两件事
-
requestLayout()
检查线程,标记状态后进入scheduleTraversals()
public void requestLayout() { if (!mHandlingLayoutInLayoutRequest) { checkThread(); mLayoutRequested = true; scheduleTraversals(); } }
scheduleTraversals()
- 添加同步屏障
- 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; }
-
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中包括
- 将Activity中的mDecor与Window中decor关联
- WindowManagerGlobal中建立ViewRootImpl、DecorView、WindowManager.LayoutParams的关联
- 调用ViewRootImpl#setView,将ViewRootImpl包装为IWindow添加到WMS中,并调用requestLayout显示UI