正所谓,世间万物皆有生命,作为Android四大组件之一的Activity也具有其自己不同的生命阶段,为了能够更加深入的理解Activity,方便以后在开发项目中能够如鱼得水,今天有必要带大家来一起探寻一下Activity生命周期的奥秘!
一.Activity简介
作为Android四大组件之一,该组件为用户提供了一个屏幕,用户在这个屏幕上进行操作来完成一定的功能,也可以理解为是一个界面, Android系统中通过活动栈来对Activity进行管理,而Activity自身则通过其自己的生命周期来使自己被创建与销毁,既然如此,就来我们来看看Activity都有哪些生命周期?
二.Activity生命周期详解
先来看看这张非常经典的生命周期流程图:
大家一定对这幅图很熟悉吧,此前有许多关于Activity生命周期的文章,都是结合这幅图来进行讲解,但是基本都是通过翻译Android API,不是很好理解并且过于官方,希望大家可以通过我的总结,使得自己受益匪浅。
Android系统中的Activity类定义了一系列的回调方法,当Activity的状态发生改变时,相应的回调方法将会自动执行,当Activity启动之后,随着应用程序的运行,其自身会不断的在各种状态之间进行切换,相应的回调方法也将被执行,我们只需选择性的重写这些方法即可进行相应的业务处理,这些状态之间的转换就构成了Activity的生命周期。在Activity生命周期中,主要有以下几种方法:
onCreate():创建Activity时被回调,用作初始化信息,例如:通过setContentView()方法呈现当前UI布局、初始化该项目中必要的控件信息等。
onStart():启动Activity时被回调,此时的Activity已经显示,但是不能和用户进行交互,只是可以看到。
onResume():当此方法被回调时,说明该Activity已经可以和用户进行交互,获得了焦点(例如:对按钮进行监听等)。
onPause():当此方法被回调时,表示Activity处于暂停状态,也可以理解为该界面被部分遮盖。一般情况下onStop()方法会紧接着被回调,但通过流程图我们还可以看到一种情况是onPause()方法执行后直接执行了onResume方法,这属于比较罕见的现象了,可以通过Activity跳转时把跳转到第二个界面主题设置为Dialog对话框模式来实现,接下来会在代码中为大家讲解!
onStop(): 当此方法被回调时,表示Activity处于停止状态,也可以理解为该界面被全部遮盖。此时的Activity不可见,但是没有被完全销毁,仍在后台中运行。
onRestart():当此方法被回调时,表示Activity正在重新启动,这种情况一般是用户打开了一个新的Activity时,当前的Activity就会被全部遮盖(onPause和onStop被执行了),接着又返回到当前Activity页面时。也就是说从一个界面返回到之前的界面。
onDestroy():当此方法被回调时,表示该Activity正在被销毁,生命到此结束。一般我们可以在此方法中做一些回收工作和终的资源释放。
实践是检验真理的唯一标准!接下来我们通过一个Demo来验证上面流程中的几种比较重要的情况,同时来观察生命周期方法的回调时机。
三.检验Activity生命周期情况
需求:实现两个页面间的跳转,并且在各自Activity中重写以上七种生命周期回调方法,在每个方法中通过Log.i在日志中打印输出,终来判断生命周期方法的回调时机。
代码如下:
第一界面的UI部分
xmlns:tools="//schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.test0104_life.MainActivity" >
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="这是第一页面"
android:textSize="30sp" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:onClick="click"
android:text="点击跳转" />
跳转到第二界面的UI部分
android:layout_width="match_parent"
android:layout_height="match_parent" >
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="这是第二页面"
android:textSize="30sp"
android:layout_centerHorizontal="true" />
第一界面的java代码:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.i("tag", "First onCreat is called!!!"); }
public void click(View v) {
Intent i = new Intent(this, SecondActivity.class);
startActivity(i); }
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Log.i("tag", "First onStart is called!!!"); }
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Log.i("tag", "First onResume is called!!!"); }
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
Log.i("tag", "First onPause is called!!!"); }
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Log.i("tag", "First onStop is called!!!"); }
@Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
Log.i("tag", "First onRestart is called!!!"); }
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.i("tag", "First onDestroy is called!!!"); } }
第二界面的java代码:
public class SecondActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_activty);
Log.i("tag", "Second onCreate is called!!!"); }
@Override
protected void onStart() {
// TODO Auto-generated method stub
super.onStart();
Log.i("tag", "Second onStart is called!!!"); }
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
Log.i("tag", "Second onResume is called!!!"); }
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
Log.i("tag", "Second onPause is called!!!");
}
@Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
Log.i("tag", "Second onStop is called!!!"); }
@Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
Log.i("tag", "Second onRestart is called!!!"); }
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
Log.i("tag", "Second onDestroy is called!!!"); } }
下面我们通过Log打印来分析几种生命周期方法的调用情况:
1.当我们成功运行Demo时,第一个界面被创建,调用结果如下:
分析:从Log中我们可以看出Activity启动后,先调用了onCreate方法,然后是onStart方法,后是onResume方法,获得焦点,可以和用户进行交互。
执行步骤: First onCreate→First onStart→First onResume
2.成功运行后,点击Home键,调用结果如下:
分析:点击Home键,该程序在后台运行,没有被彻底销毁,不需调用onDestroy方法,所以,先调用onPause方法,界面被部分遮盖,之后再调用onStop方法,界面被全部遮盖。
执行步骤: First onPause→First onStop
3.再次运行该程序,调用结果如下:
分析:因为该程序一直在后台运行,所以再次启动该程序时,直接调用onRestart方法,重新启动,之后执行onStart方法,后是onResume方法
执行步骤:First onRestart→First onStart→First onResume
4.点击按钮跳转到第二个界面时,调用结果如下:
分析:当进行第二界面跳转时,第一界面先被部分遮盖,调用onPause,之后创建第二界面的流程和创建第一界面相同,先调用了onCreate方法,然后是onStart方法,后是onResume方法,成功创建之后第一界面被全部遮盖,执行onStop方法。(也可以理解为第二界面缓缓的把第一界面进行遮盖) 执行步骤:First onPause→Second onCreate→Second onStart→Second onResume→First onStop
5.点击Back键,返回到第一界面,调用结果如下:
分析:返回到第一界面时,第二界面先被部分遮盖,之前没有被销毁的第一界面重新启动,调用onRestart方法,然后是onStart方法,后是onResume方法,获得焦点,再次的可以和用户进行交互。之后第二界面才被全部遮盖,并且终被彻底销毁,执行onDestroy方法。
执行步骤:Second onPause→First onRestart→First onStart→First onResume→Second onStop→Second OnDestroy
6.此前我们提到过,流程图还可以看到一种情况是onPause方法执行后直接执行了onResume方法。我们将其第二个界面主题设置为Dialog对话框模式。
修改代码如下:
android:label="@string/app_name"
android:theme="@style/MyTheme" >
点击按钮跳转第二界面,调用结果如下:
分析:跳转到第二界面时,第一界面被部分遮盖,调用onPause,第二界面被创建,和之前的流程相同,先调用了onCreate方法,然后是onStart方法,后是onResume方法,但是!当第二界面被创建完成时,第一界面也不会被全部遮盖,不会调用onStop方法,因为主题为Dialog对话框,界面较小,遮盖不住之前的第一界面。
执行步骤:First onPause→Second onCreate→Second onStart→Second onResume
接下来点击Back键,返回到第一界面:
分析:由于此前的第一界面没有被全部遮盖,所以直接调用onResume方法,再次获得焦点,并且与用户进行交互。
执行步骤:Second onPause→Firat onResume→Second onStop→Second onDestroy