Android 的生命周期网上有很多关于它的介绍, 因此这篇文章对一些基础的东西只会带过, 只记录一下自己在复习是的一些问题. 这篇文章中的内容主要来自《Android 开发艺术探讨》这本书, 书中内容是基于 android5.0. 文章最后有一个这本书的网上地址, 手上没有这本书的话可以参考该地址; 这文章的测试代码可以在 GitHub https://github.com/hdd1024/AndroidReView 查看.
目录
使用场景
生命周期配对理解生命周期
当 AActivity 切换 BActivity 那么 A 的 onPause 和 B 的 onResume 那个先执行
一些特殊情况生命周期的调用
onSaveInstanceState 和 onRestoreInstanceState 方法
横竖屏配置
进程优先级
1. 使用场景
onCreate 可用于做布局资源的加载和初始化
onStart 当前 activity 是用户可见状态, 但没有焦点, 用户不能交互, 一般可在当前方法做一些动画的初始化操作
onPause 可做一些储存数据, 停止动画等, 不能太耗时
onStop 此时 activity 对用户是不可见的, 在系统内存紧张的情况下, 可能会被回收. 一般在当前方法可做资源回收
2. 生命周期配对理解生命周期
创建销毁角度 onCreate 和 onDestroy 只会调用一次
是否可见角度 onStart 和 onStop 多次调用
前台显示角度 onResume 和 onPause 多次调用
3. 当 AActivity 切换 BActivity 那么 A 的 onPause 和 B 的 onResume 那个先执行
AActivity 的 onPause 先执行具体可以查看 ActivityStack 类中 resumeTopActivityInnerLocked 方法的代码:
参考《Android 开发艺术探索》第一章第五页
- // 暂停当前 activity
- boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
- boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
- if (mResumedActivity != null) {
- pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
- if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing" + mResumedActivity);
- }
- if (pausing) {
- if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG,
- "resumeTopActivityLocked: Skip resume: need to start pausing");
- if (next.App != null && next.App.thread != null) {
- mService.updateLruProcessLocked(next.App, true, null);
- }
- if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
- return true;
- }
BActivity 的生命周期调用过程, 可参考 ActivityThread 的 handleLaunchActivity 方法.
4. 一些特殊情况生命周期的调用
正常情况下 onPause 被调用后, 紧接着会调用 onStop. 如果在切换页面时候快速返回当前 activity, 那么 onResume 会被调用, 即只会调用 onPause 方法而 onStop,onRestart 和 onStart 方法不会被调用.
一般情况打开新的 activity 当前 activity 进入后台时候, 回调如下: onPause-->onStop. 如果新的 activity 采用了透明主题, 那么当前 activity 就不会调用 onStop
(因为当前 activity 是可见的)
5. onSaveInstanceState 和 onRestoreInstanceState 方法
onSaveInstanceState 主要用于保存当前 activity 转态
onRestoreInstanceState 用于恢复页面数据
调用时机
onSaveInstanceState: onPasue-->onSaveInstanceState-->onStop
注: 网上很多篇文章写道该方法与 onPasue 方法不能确定谁先调用, 自己在测试和网上有出入, 如果写的有误, 请留言.
按下 Home 键返回桌面
电源键关闭屏幕
启动其它 Activity
横竖屏切换
- onRestoreInstanceState:
- onCreate-->onStart-->onRestoreInstanceState
屏幕旋转
内存不足应用被杀死或者 activity 被销毁.
在特殊情况下 (屏幕旋转)activity 被重新创建, 系统默认会为我们保存当前 activity 的一些数据. 如文本框的输入, listview 的滚动位置等; 需要注意的是该 view 要有 id 系统才能为我们保存它的状态.
每个 view 都有对应的 onSaveInstanceState 和 onRestoreInstanceState 方法, 可以通过查看 view 的这两个方法来知道系统能们恢复 view 的那些数据.
下面为测试代码:
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- Log.i(TAG, "==onRestoreInstanceState()==");
- String test1 = savedInstanceState.getString("test1");
- //onRestoreInstanceState() 恢复的数据是有价值的,
- // 可以不用做非空判断. 但是 onCreate() 要做非空判断
- Log.i(TAG, "onRestoreInstanceState():" + test1);
- }
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- Log.i(TAG, "==onSaveInstanceState()==");
- outState.putString("test1", "这是 activity 销毁前保存的数据");
- }
当屏幕旋转后 activity 被重建, 打印的日志为:
- ==onCreate()==
- ==onStart()==
- ==onResume()==
- ==onPause()==
- ==onSaveInstanceState()==
- ==onStop()==
- ==onDestroy()==
************ 上面日志为 activity 被销毁 *******
- ==onCreate()==
- ==onStart()==
- ==onRestoreInstanceState()==
onRestoreInstanceState(): 这是 activity 销毁前保存的数据
==onResume()==
6. 横竖屏配置
在 AndroidManifest.xml 清单中配置 configChanges 属性
在 onCreate 方法中设置 setRequestedOrientation() 方法
- // 方法一
- <activity
- Android:name=".TestActivity"
- Android:configChanges="orientation" />
- // 方法二
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- // 禁止横屏
- setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
- }
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- Log.i(TAG, "onConfigurationChanged 配置信息:" + newConfig.orientation);
- }
7. 进程优先级
前台进程 > 可见进程 > 服务进程 > 后台进程 > 空进程
注: Android 只杀死进程, 而不是组件.
前台进程
正在与用户进行交互的 Activity
正在和当前 Activity 交互的 service
当前 service 调用了 startForground() 方法成为了前台进程
当前 service 正在执行生命周期
进程持有一个 BroadcastReceiver, 这个 BroadcastReceiver 正在执行 onReceive() 方法
可见进程
一般不会被杀死, 只有在内存极其紧张并且前台进程需要内存的情况下, 才会被杀死.
activity 处于 onPause 状态下, 例如弹出框, 加载框, 授权提示等遮盖住了 Activity
service 和一个可见 Activity 进行绑定
服务进程
只有内存不足以维持所有前台进程和可见进程运行情况下才会杀死服务进程, 否则系统会让服务进程保持运行状态.
开启一个 service 服务, 就可以认为是一个服务进程.
后台进程
系统可能随时终止它们, 以回收内存供前台进程, 可见进程或服务进程使用. 在内存不足情况下, 会先回收最早使用过的 Activity.
Activity 调用 onStop() 进入了后台用户不可见, 那么可以认为其为后台进程.
空进程
保存这种进程的原因是缓存需要
不含任何活动应用组件的进程
参考
Android 开发艺术探索完结篇 -- 天道酬勤
activity 生命周期 (这篇足够了)
Activity 生命周期相关的 7 个方法 https://www.cnblogs.com/joinrudy/p/3465442.html
Android 进程优先级: 等级低的就被 Kill 掉了 https://www.jianshu.com/p/35727ad2296a
来源: https://juejin.im/post/5c5d862ee51d457fc905d199