Android的开发中我们大部分都是和Activity打交道,而想很好的运用Activity首先必须要清楚Activity的生命周期。接下来我们就聊聊Activity的生命周期。
一、认识Activity
Activity的中文意思就是活动,代表手机屏幕的一屏,或是平板中的一个窗口,提供了和用户交互的可视化界面。Activity是用于处理UI相关业务的,比如加载界面、监听用户操作等事件。
二、Activity的状态
(一)、Running状态: 一个新的Activity启动入栈后,它在屏幕的最前端,处于栈的最顶端,此时它处于可见并可和用户交互的激活状态,Android试图尽最大可能保持它活动状态,杀死其它Activity来确保当前活动Activity有足够的资源可使用。当另外一个Activity被激活,这个将会被暂停。
(二)、Paused状态:当Activity处于此状态时,此时它依然与窗口管理器保持连接,系统继续维护其内部状态,它仍然可见,但它已经失去了焦点,故不可与用户交互。
(三)、Stopped状态: 当Activity 不可见时,Activity处于Stopped状态。当Activity处于此状态时,一定要保存当前数据和当前的UI状态,否则一旦Activity退出或关闭时,当前的数据和UI状态就丢失了
(四)、Killed状态:Activity被杀掉以后或者被启动以前,处于Killed状态。这是Activity已从Activity堆栈中移除,需要重新启动才可以显示和使用。
三、Activity的生命周期
(一)、先看下官方的基本生命周期图,可以从下图中了解Activity的大概生命周期:
(二)、生命周期的方法的介绍:
1.Activity正常的生命周期方法:
(1)onCreate方法:该方法是在Activity被创建时回调,它是生命周期第一个调用的方法,我们在创建Activity时一般 都需要重写该方法,然后在该方法中做一些初始化的操作,如:创建view、绑定数据到view。
(2)onStart方法:start表示启动,这是Activity生命周期的第二个方法。此时Activity已经可见了,但是还没出现在前台,我们还看不到,无法与Activity交互。其实将Activity的初始化工作放在这也没有什么问题,放在onCreate中是由 于官方推荐的以及我们开发的习惯。
(3)onResume方法:当此方法回调时,则说明Activity已在前台可见,可与用户交互了(处于前面所说的Active/Running形态),onResume方法与onStart的相同点是两者都表示Activity可见,只不过onStart回调时Activity还 是后台无法与用户交互,而onResume则已显示在前台,可与用户交互。当然从流程图,我们也可以看出当Activity停止后(onPause方法和onStop方法被调用),重新回到前台时也会调用onResume方法,因此我们也可以在 onResume方法中初始化一些资源,比如重新初始化在onPause或者onStop方法中释放的资源。
(4)onPause方法:当Activity要跳到另一个Activity或应用正常退出时都会执行这个方法。此时Activity显示在前台并可 见,我们可以进行一些轻量级的存储数据和初始化的工作,不能太耗时,因为在跳转Activity时只有当一个Activity执 行完 了onPause方法后另一个Activity才会启动,而且android中指定如果onPause在500ms即0.5秒内没有执行完毕的 话 就会强制关闭Activity。从生命周期图中发现可以在这快速重启,但这种情况其实很罕见,比如用户切到下一个Activity的途中按back键快速得切回来。
(5)onStop方法:紧接着onPause方法调用,此时Activity已经不再显示在用户面前了,此时新的Activity可能已经执行到onStart方法或者onResume方法了,所以此时可做一些较为重量级回收操作比方说关于数据库的一些读写操作等。
(6)onRestart方法:表示Activity正在重新启动,当Activity由不可见变为可见状态时,该方法被回调。这种情况一 般是用户打开了一个新的Activity时,当前的Activity就会被暂停(onPause和onStop被执行了),接着又回到当前 Activity页面时,onRestart方法就会被回调。 这里一般不做什么操作。
(7)onDestroy方法:该方法表示Activity生命周期中的最后一个方法,表示Activity方法将会被销毁,此时我们可以做 一些回收操作和最终的资源释放。这里需要提到的一点是,即使一个Activity被销毁后app内部的static变量是不会被销毁的,因为static变量是全局的,activity销毁但是该app的进程并没有被杀死。所以说这一点尤为需要注意我们的static变量的使用,否则稍有不慎再次启动该activity的时候该static变量就会是一个dirty data!
2、异常生命周期的两个方法:
(1)onSaveInstanceState方法:是用来保存UI状态的,在Activity杀死之前,你可以使用它保存你所想保存的东西,当 targetSdkVersion小于3时onSaveInstanceState是在onPause方法中调用的,而大于3时是在onStop方法中调用的。
(2)onRestoreInstanceState方法:恢复界面的状态,是在onStart之后、onResume之前调用的。
(三)、了解了生命周期的方法,接下来我们来分析生命周期方法调用的顺序。
1.以下是验证方法调用顺序的实例代码:
public class MainActivity extends Activity {
public static final String TAG = "MainActivity";
Button bt;
/** * Activity创建时被调用 * @param savedInstanceState */ @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
Log.e(TAG, "onCreate is invoke!!!");
bt= (android.widget.Button) findViewById(R.id.bt);
bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
android.content.Intent i = new android.content.Intent(MainActivity.this,SecondActivity.class);
startActivity(i);
}
});
}
/** * Activity从后台重新回到前台时被调用 */ @Override
protected void onRestart() {
super.onRestart();
Log.e(TAG, "onRestart is invoke!!!");
}
/***Activity创建或者从后台重新回到前台时被调用 */
@Override
protected void onStart() {
super.onStart();
Log.e(TAG, "onStart is invoke!!!");
}
/***Activity创建或者从被覆盖、后台重新回到前台时被调用 */
@Override
protected void onResume() {
super.onResume();
Log.e(TAG, "onResume is invoke!!!");
}
/*** Activity被覆盖到下面或者锁屏时被调用 */
@Override
protected void onPause() {
super.onPause();
Log.e(TAG, "onPause is invoke!!!");
}
/** *退出当前Activity或者跳转到新Activity时被调用 */
@Override
protected void onStop() {
super.onStop();
Log.e(TAG, "onStop is invoke!!!");
}
/** *退出当前Activity时被调用,调用之后Activity就结束了 */
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy is invoke!!!");
}
}
2.下面我们分析各种情况下,生命周期方法执行顺序:
(1)我们先来分析Activity启动过程中所调用的生命周期方法,运行程序如下:
04-03 11:20:42.107 26915-26915/com.jiusi.equiview E/MainActivity: onCreate is invoke!!!
04-03 11:20:42.157 26915-26915/com.jiusi.equiview E/MainActivity: onStart is invoke!!!
onResume is invoke!!!
从Log中我们可以看出Activity启动后,先调用了onCreate方法,然后是onStart方法,最后是onResume方法,进入运行状 态,此时Activity已在前台显示。因此, Activity启动–>onCreate()–>onStart()–>onResume()依次被调用。
(2)当前Activity创建完成后,按Home键回到主屏。运行如下:
04-03 11:22:00.447 26915-26915/com.jiusi.equiview E/MainActivity: onPause is invoke!!!
04-03 11:22:01.257 26915-26915/com.jiusi.equiview E/MainActivity: onStop is invoke!!!
我们在Activity创建完成后,点击Home回调主界面时,可以发现此时onPause方法和onStop方法被执行,也就是点击Home键回到主界面(Activity不可见)–>onPause()–>onStop()依次被调用。
(3)当前Activity创建完成后,按Back键回到主屏。运行如下:
04-03 11:23:15.097 26915-26915/com.jiusi.equiview E/MainActivity: onPause is invoke!!!
04-03 11:23:15.707 26915-26915/com.jiusi.equiview E/MainActivity: onStop is invoke!!!
04-03 11:23:15.717 26915-26915/com.jiusi.equiview E/MainActivity: onDestroy is invoke!!!
我们在Activity创建完成后,点击back键返回时,相当于退出了当前Activity,Activity将被销毁,可以发现此时onPause方法、onStop方法、onDestroy方法被执行,也就是点击Back键返回时(Activity不可见)–>onPause()–>onStop()–>onDestroy()依次被调用。
(4)当我们在原有的Activity的基础上打开新的Activity时。运行如下:
04-03 11:26:00.767 29335-29335/com.jiusi.equiview E/MainActivity: onPause is invoke!!!
04-03 11:26:00.817 29335-29335/com.jiusi.equiview E/SecondActivity: onCreate is invoke!!!
04-03 11:26:00.827 29335-29335/com.jiusi.equiview E/SecondActivity: onStart is invoke!!!
onResume is invoke!!!
04-03 11:26:01.087 29335-29335/com.jiusi.equiview E/MainActivity: onStop is invoke!!!
我们可看到首先调用了原来的Activity的onPause方法,接着调用新的Activity的onCreate(),onStart(),onResume()方法,然后再调用原来Activity的onStop方法。也就是说 在原Activity的基础上开启新的Activity,原Activity生命周期执行方法顺序为–>onPause()–>onStop(),事实上跟点击home键是一样的。但是这里有点要注意的是如果新的Activity使用了透明主题,那么当前Activity不会回调onStop方法。同时我们发现新Activity(SecondActivity)生命周期方法是在原Activity的onPause方法执行完成后才可以被回调,这也就是前面我们为什么说在onPause方法不能操作耗时任务的原因了。
(5)当我们在新的Activity的基础上返回时。运行如下:
04-03 11:29:47.227 29335-29335/com.jiusi.equiview E/SecondActivity: onPause is invoke!!!
04-03 11:29:47.257 29335-29335/com.jiusi.equiview E/MainActivity: onRestart is invoke!!!
onStart is invoke!!!
onResume is invoke!!!
04-03 11:29:47.517 29335-29335/com.jiusi.equiview E/SecondActivity: onStop is invoke!!!
04-03 11:29:47.527 29335-29335/com.jiusi.equiview E/SecondActivity: onDestroy is invoke!!!
我们可以看到执行完当前Activity的onPause方法后,接着就依次执行前一个Activity的onRestart、onStart、onResume,此时前一个Activity已经显示在前台了,接着就调用了当前Activity的onStop、onDestroy方法,当前Activity就销毁了。
我们总结下方法的调用顺序,当Activity启动时,依次会调用onCreate,onStart,onResume,而当Activity退居后台时(不可见,点击Home或者被新的Activity完全覆盖),onPause和onStop会依次被调用。当Activity重新回到前台(从桌面回到原Activity或者被覆盖后又回到原Activity)时,onRestart,onStart,onResume会依次被调用。当Activity退出销毁时(点击back键),onPause,onStop,onDestroy会依次被调用,到此Activity的整个生命周期方法回调完成。
现在我们再回头看看之前的流程图,应该是相当清晰明了了吧。这就是Activity整个典型的生命周期过程。
3.生命周期异常方法:
Activity的 onSaveInstanceState 和 onRestoreInstanceState并不是生命周期方法,它们不同于 onCreate、onDestroy等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,onSaveInstanceState会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause适合用于数据的持久化保存。
在Activity被杀掉之前调用保存每个实例的状态,以保证该状态可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle) (传入的Bundle参数是由onSaveInstanceState封装好的)中恢复。这个方法在一个Activity被杀死前调用,当该Activity在将来某个时刻回来时可以恢复其先前状态。
例如,如果ActivityB启用后位于ActivityA的前端,在某个时刻ActivityA因为系统回收资源的问题要被杀掉,A通过onSaveInstanceState将有机会保存其用户界面状态,使得将来用户返回到ActivityA时能通过onCreate(Bundle)或者onRestoreInstanceState(Bundle)恢复界面的状态。
以上就是Activity生命周期的相关方法的一些介绍,有不合理之处请多指教!