A.onPause -> B.onNewIntent -> B.onRestart -> B.onStart -> B.onResume -> A.onStop -> ( 如果 A 被移出栈的话还有一个 A.onDestory)
把几种情况都回答出来就能加分啦,同时也要做好聊 launchMode 的准备。
我们知道,生命周期回调都是 AMS 通过 Binder 通知应用进程调用的;而弹出 Dialog、Toast、PopupWindow 本质上都直接是通过 WindowManager.addView() 显示的(没有经过 AMS),所以不会对生命周期有任何影响。
如果是启动一个 Theme 为 Dialog 的 Activity , 则生命周期为:
A.onPause -> B.onCrete -> B.onStart -> B.onResume
注意这边没有前一个 Activity 不会回调 onStop,因为只有在 Activity 切到后台不可见才会回调 onStop;而弹出 Dialog 主题的 Activity 时前一个页面还是可见的,只是失去了焦点而已所以仅有 onPause 回调。
虽然我们设置 Activity 的布局一般都是在 onCreate 方法里调用 setContentView 。里面是直接调用 window 的 setContentView,创建一个 DecorView 用来包住我们创建的布局。详情如下:
PhoneWindow.java
public void setContentView(int layoutResID) {
if (mContentParent == null) {
installDecor();
}
…
// 加载布局,添加到 mContentParent
// mContentParent 又是 DecorView 的一个子布局
mLayoutInflater.inflate(layoutResID, mContentParent);
}
然而这一步只是加载好了布局,生成一个 ViewTree , 具体怎么把 ViewTree 显示出来,答案就在下面:
ActivityThread.java
public void handleResumeActivity(…){
// onResume 回调
ActivityClientRecord r = performResumeActivity(…)
final Activity a = r.activity;
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
ViewManager wm = a.getWindowManager();
wm.addView(decor, l);// 重点
}
}
WindowManager 的 addView 方法最终将 DecorView 添加到 WMS ,实现绘制到屏幕、接收触屏事件。具体的调用链如下:
WindowManagerImpl.addView
-> WindowManagerGlobal.addView
-> ViewRootImpl.setView
-> ViewRootImpl.requestLayout() // 执行 View 的绘制流程
// 通过 Binder 调用 WMS ,WMS 会添加一个 Window 相关的对象
// 应用端通过 mWindowSession 调用 WMS
// WMS 通过 mWindow (一个 Binder 对象) 调用应用端
mWindowSession.addToDisplay(mWindow)
综上,在 onResume 回调之后,会创建一个 ViewRootImpl ,有了它之后应用端就可以和 WMS 进行双向调用了。
如果你看到了这里,觉得文章写得不错就给个赞呗?如果你觉得那里值得改进的,请给我留言。一定会认真查询,修正不足。谢谢。
最后针对Android程序员,我这边给大家整理了一些资料,包括不限于高级UI、性能优化、移动架构师、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter等全方面的Android进阶实践技术;希望能帮助到大家,也节省大家在网上搜索资料的时间来学习,也可以分享动态给身边好友一起学习!
%BD%95%E9%9D%A2%E8%AF%95%E6%8B%BF%E9%AB%98%E8%96%AA%EF%BC%81.md)