《Android开发艺术探索》买了好久了,将近有两年了,一直没有好好系统的看过,在浑浑噩噩的过日子,浪费好多时间;现在从头再来,坚持下去给自己一个希望。
典型的生命周期
7个生命周期方法
- onCreate:Activity正在被创建
- 初始化布局资源和数据
- onRestart:Activity正在重启启动,从不可见变为可见状态
- 按Home键返回桌面,再点击桌面图标返回App
- 启动新Activity后,再返回这个Activity
- onStart:Activity正在被启动,已经可见了,但不在前台
- 没有焦点无法交互
- onResume:Activity已经可见了,显示到前台
- 有焦点可以交互
- onPasue:Activity正在停止
- 可以做一些存储数据、停止动画等工作
- 不适合做耗时的任务,会影响到新Activity的onResume,必须先执行完onPasue才会执行新Activity的onResume(必须先执行完onPause,才会启动新的Activity,在onPause做耗时工作会延迟新Activity启动)。
- onStop:Activity即将停止
- 一些资源回收的工作,不能太耗时(??)
- 太耗时,会影响从新Activity返回旧Activity的时间,不能及时返回,需待旧Activity中的onStop执行完后,才能返回。
onDestroy:Activity即将销毁
- 可以回收和释放资源工作
注:
“可见”只是说显示,但不一定是用户可以看到、交互;
“前台”就是看得见、摸得着,摸摸有反应。
生命周期切换过程
- 启动新Activity
- onCreate -> onStart -> onResume
- 打开新Activity或按Home键返回桌面
- 正常情况:onPause -> onStop
- 新Activity为透明主题:onPause (onStop不执行)
- 再次回到Activity(桌面返回或者新Activity返回)
- 正常情况:onRestart -> onStart -> onResume
- 新Activity为透明主题:onResume
- 按返回back键返回时
- onPause -> onStop -> onDestroy
异常情况下的生命周期
资源相关的系统配置发生改变或者系统内存不足时,Activity会被杀死,异常终止。
生命周期及数据存储与恢复
横竖屏旋转切换属于系统配置发生改变的情况,默认情况下,不做任何处理,Activity会被销毁并重新创建,整个生命周期如下:
- 销毁过程:onPause -> onSaveInstanceState -> onStop -> onDestroy
- 重建过程:onCreate -> onStart -> onRestoreInstanceState -> onResume
onSaveInstanceState和onRestoreInstanceState 只有在Activity异常终止时才会被回调,用来存储和恢复数据,其他情况是不会被触发这个过程。
数据恢复在 onCreate 或者 onRestoreInstanceState 中进行都可以,但是官方文件建议在 onRestoreInstanceState 中,因为它被调用时 bundle 一定是有值的,不需要判断。
数据存储与恢复的工作流程
- Activity意外终止,调用onSaveInstanceState去保存数据
- 然后Activity委托Window保存数据
- 接着Window在委托它顶级容器(ViewGroup)保存数据
最后,顶级容器(ViewGroup)通知子view去保存数据。
委托思想:上层委托下层,父容器委托子元素处理
比如View绘制过程、事件分发都是类似的思想。
系统内存不足,优先级低的Activity会被杀死
- 前台Activity:可见可与用户进行交互的Activity,优先级最高
- 可见非前台Activity:可见但不能与用户进行交互,又位于后台的Activity,比如在Activity显示Dialog。优先级次之
- 后台Activity:不可见又无法交互的Activity,一般是执行了onStop方法,优先级最低。
指定系统属性配置,使Activity不销毁重建
实际开发中,很多情况并不希望系统配置改变后,Activity生命周期销毁又重建,比如视频横竖屏播放等等。
实现上面的需求,在可AndroidMainfest中指定Activity的configChanges属性值,如下:
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize" />
给configChanges指定了上面的属性值,Activity在横竖屏旋转时,onSaveInstanceState和onRestoreInstanceState及其他周期方法均不会被回调,只会回调onConfigurationChanged,可在其做一些业务需求操作,如下:
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
if (newConfig.orientation==Configuration.ORIENTATION_PORTRAIT){
Log.d(TAG, "竖屏业务逻辑……");
}else if (newConfig.orientation==Configuration.ORIENTATION_LANDSCAPE){
Log.d(TAG, "横屏业务逻辑……");
}
}
configChanges的属性值有很多,常见的如下:
- orientation:屏幕方法发生改变,比如旋转手机屏幕
- keyboardHidden:键盘发生了改变,比如用户调出了键盘或者关闭
- locale:系统语言发生了改变。
Activity的一些特殊情况
按返回键,Activity不销毁(不执行onDestroy)
重写onKeyDown方法,监听返回键事件,最后调用moveTaskToBack方法,如下:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
//监听返回键按钮
if (keyCode==KeyEvent.KEYCODE_BACK){
//将当前Activity移到Activity栈后面
moveTaskToBack(true);
return true;
}
return super.onKeyDown(keyCode, event);
}
Activity的onTrimMemory方法
从字面可以看出与内存有联系,当用户按Home键或back键导致界面UI被隐藏了不可见了,此时可以调用onTrimMemory方法进行一些资源内存的释放。Android代码内存优化建议-OnTrimMemory优化
@Override
public void onTrimMemory(int level) {
super.onTrimMemory(level);
}
Activity的主题设置
android:theme="@style/Theme.AppCompat.Dialog"
设置该主题后,Activity会以对话框的形式弹出,此时onStop方法不会被调用,旧Activity处于可见但非前台的状态(与透明主题一样的)。
android:theme="@android:style/Theme.Translucent"
或
android:theme="@android:style/Theme.Dialog"
设置上面类似的主题,在启动中可能会报java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity. 解决方案
关于透明主题设置如下:
// 一、style 文件,注意一点parent需继承Theme.AppCompat下
<style name="TransparencyTheme" parent="AppTheme">
<item name="android:windowBackground">@color/colorTransparency</item>
<item name="android:windowIsTranslucent">true</item>
</style>
// 二、color颜色
<color name="colorTransparency">#00000000</color>
//三、AndroidMainfest引用
android:theme="@style/TransparencyTheme"