Andriod : activity的生命周期与设备配置变更

一、activity的生命周期

每个Activity实例都有其生命周期。在其生命周期内,activity在 运行暂停暂存停止不存在 这四种状态间转换。每次状态转换时,都有相应的Activity方法发消息通知activity。下图显示了activity的 生命周期状态 以及 状态切换 时系统调用的方法。
在这里插入图片描述

上图中的 暂存 状态是一个特殊的状态,在该状态下,activity对象已经被销毁,但是操作系统将activity记录对象保存下来了,在需要恢复activity时,操作系统可以使用暂存的activity记录重新激活activity。
[注]
activity进入暂存状态并不一定需要调用onDestroy()方法,不过,onStop()和
onSaveInstanceState(Bundle)是两个可靠的方法。
因而,常见的做法是:
1、覆盖onSaveInstanceState(Bundle)方法,在Bundle对象中,保存当前activity的小的或暂存状态的数据;
2、覆盖onStop()方法,保存永久性数据,如用户编辑的文字等,onStop()方法
调用完,activity随时会被系统销毁,所以用它保存永久性数据。

那么,暂存的activity记录到底可以保留多久?前面说过,用户按了后退键后,系统会彻底销毁
当前的activity。此时,暂存的activity记录同时被清除。此外,系统重启的话,暂存的activity记录
也会被清除。

activity的一般状态
在这里插入图片描述

用户对手机的不同操作对应用程序的影响:

利用Andriod Studio中的LogCat可以将运行处的日志信息输出到窗口,因此可以利用LogCat探究Activity的运行状况。

由于Activity实例切换状态时,会调用onCreate()、onResume()、onPause()、onStart()、onStop()和onDestory()方法中的一种或多种,因此我们可以在这些方法中加入Log信息,查看在不同的操作下这些方法的调用情况。

常用日志记录方法说明:
在这里插入图片描述

通常做法是:
利用Log类中的public static int d(String tag,String msg)方法来为方法添加Log信息,实现追踪。

1、当用户启动应用程序时:

onCreate(Bundle)、onStart() 和 onResume()这三个生命周期方法被调用了。Activity实例从 不存在 状态转换到 运行 状态(在内存里,用户可见,活动在前台)。

2、在应用正常运行时按下手机的返回键:

Activity 的onPause() 、onStop() 和onDestroy() 方法将会被调用。Activity从 运行 状态转换到 不存在 状态

单击设备的后退键,相当于告诉Android系统:“activity已用完,现在不需要它了。”随即,
系统就销毁了该activity的视图及其内存里的相关信息。这实际是Android系统节约使用设备有限资源的一种方式。

3、在应用正常运行时按下手机的主屏幕键(Home键)

Activity的 onPause()和 onStop()方法将会被调用,Activity从 运行 状态转换到 停止 状态
单击主屏幕键,相当于告诉Android系统:“我去别处看看,稍后可能回来。”此时,Android系统会先暂停,再停止当前activity。这表明,Activity实例已处于停止状态(在内存中,但不可见,不会活动在前台)。这样,Android系统就能快速响应,重启Activity,回到用户离开时的状态。

(需要注意的是,停止的activity能够存在多久,谁也无法保证。系统需要回收内存时,它将首先销毁那些停止的activity。)

4、在应用正常运行时按下手机的Home键,再按下概览屏键(显示后台应用的按键)点开在后台的刚刚运行过的应用

重新打开后台的应用,只用调用 onStart()和 onResume()方法,Activity从 停止 状态转换到 运行 状态
用户按了主屏幕键后,Activity最后进入停止状态,再次调出应用时,Activity只需要重新启动(进入暂停状态,用户可见),然后继续运行(进入运行状态,活动在前台)。不需要重新onCreate()。

5、旋转设备的屏幕

onPause()、 onStop()、 onDestroy()、onCreate()依次被调用,可见设备旋转时,系统会销毁当前Activity实例,然后创建一个新的Activity实例。也就是说旋转设备会让应用重启,这很可能会造成数据丢失!!!

这就涉及到设备配置和备选资源的问题了

二、备选资源和数据保存

备选资源

旋转设备会改变 设备配置(device configuration)。设备配置 实际是一系列特征组合,用来描述设备当前状态。这些特征有:屏幕方向、屏幕像素密度、屏幕尺寸、键盘类型、底座模式以及语言等。

通常,为匹配不同的设备配置,应用会提供不同的备选资源。

运行时配置变更 (runtime configuration change)发生时(例如当屏幕方向改变时)可能会有更合适的资源来匹配新的设备配置。于是,Android销毁当前activity,为新配置寻找最佳资源,然后创建新实例使用这些资源。

如果你给应用准备了一个垂直布局和一个水平布局,当屏幕方向从纵向变为横向时,Andriod可能会觉得这时候更适合水平布局,因而会采用水平布局的显示视图。

保存数据

事实证明,当手机屏幕方向改变时,activity的重启会导致部分数据的丢失。
为了应对这一点,我们需要覆盖Activity的onSaveInstanceState()方法

protected void onSaveInstanceState(Bundle outState)

该方法通常在onStop()方法之前由系统调用,除非用户按后退键。(记住,按后退键就是告诉Android,activity用完了。随后,该activity就完全从内存中被抹掉。

方法onSaveInstanceState(Bundle)的默认实现要求所有activity视图将自身状态数据保存在 Bundle对象 中。Bundle是存储字符串键与限定类型值之间映射关系(键–值对)的一种结构。
Bundle作为参数传入onCreate(Bundle)方法:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
}

覆盖onCreate(Bundle)方法时,我们实际是在调用activity超类的onCreate(Bundle)方法,并传入收到的bundle。在超类代码实现里,通过取出保存的视图状态数据,activity的视图层级结构得以重建。

在Activity类中定义一个常量,作为标签常量。

在onSaveInstanceState(Bundle)方法中 使用 Bundle实例的putInt()等方法可以将指定数据和你规定的标签常量进行绑定,这里的putInt()可以将标签常量和一个int型变量绑定。

然后再onCreate(Bundle)方法中,使用传进来的Bundle实例的getInt()方法获取与标签常量绑定的变量值,并重新赋值给变量。实现了数据的保存。
这样,无论怎么旋转屏幕,数据都不会丢失。

[注]
1、覆盖onSaveInstanceState(Bundle)方法并不仅仅用于处理与设备旋转相关的问题。用户离开当前activity用户界面,或Android需要回收内存时,activity也会被销毁。(例如,用户按了主屏幕键,然后播放视频或玩起游戏。)

2、基于用户体验考虑,Android从不会为了回收内存,而去销毁可见的activity(处于暂停或运行状态)。只有在调用过onStop()并执行完成后,activity才会被标为可销毁。

3、系统随时会销毁掉已停止的activity 。不用担心数据丢失, activity 停止时, 会调用onSaveInstanceState(Bundle)方法的。所以,解决旋转屏幕数据丢失问题,就是抢在系统销毁activity之前保存数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值