Android基础之Activity生命周期

之前一直对Activity的生命周期不是很清楚,感觉很模糊。前两天也看了下任玉刚书里对Activity生命周期的讲解,今天特意写了个程序验证了下Activity的生命周期内各个回调的执行情况,为了避免多段时日又忘了,干脆对这次的理解总结下,俗话说好记性不如烂笔头,没事的时候可以回过头来再看看。

我们先来看一张非常经典的Activity生命周期流程图:

Activity的生命周期大致有如下几个成果:

  1. 启动Activity:系统会先调用onCreate,然后调用onStart,最后调用onResume,此时Activity进入前台处于运行状态。如图:

  1. 当前Activity被其他Activity覆盖,且覆盖的这个Activity是为透明:系统只会调用onPause,此时Activity处于后台可见暂停运行状态。如图:

  1. 当前Activity被其他Activity覆盖,且覆盖的这个Activity为非透明:系统处理过程与步骤4中的过程是一样的。如图:

  1. 手机锁屏或按下了Home键:系统会先调用onPause,最后调用onStop,此时Activity处于后台非可见暂停运行状态。如图:

  1. 如果在步骤2时,用户后退回到了此Activity:系统会调用onResume,此时Activity回到前台继续运行。如图:

  1. 如果在步骤3和4时,用户后退或解锁回到了此Activity:系统会调用onRestart,然后调用onStart,最后调用onResume,然后此Activity回到前台继续运行。如图:

  1. 当Activity处于被覆盖或后台不可见时(即步骤3和4),系统内存不足时会杀死该Activity(系统杀死Activity时,步骤3与4的Activity的被杀优先级会比步骤2高),这时如果用户后退回到该Activity,系统会重新执行onCreate,onStart,onResume进入运行状态。此过程不好验证,不提供图片了。

  2. 用户退出Activity时:系统会先执行onPause,然后执行onStop,最后执行onDestory方法结束此Activity的运行。如图:

  1. 系统内存不足杀死Activity结束运行时的生命周期函数执行情况我目前无法验证,暂时不是很清楚。

从上面的生命周期过程来看,主要涉及到了7个生命周期函数,下面是我对于每个生命周期主要作用的理解:

  1. onCreate:用于Activity的初始化,例如设置布局,初始化相关布局控件等。

  2. onStart:设置Activity窗口可见

  3. onResume:让Activity窗口处于系统前台

  4. onRestart:在Activity由不可见回到可见时,需要通过此方法唤起onStart的执行

  5. onPause:让Activity窗口退出系统前台(参照上面的过程2理解),与onResume方法刚好是一对

  6. onStop:让Activity窗口不可见(参照上面的过程3和过程4理解),与onStart方法刚好是一对

  7. onDestory:结束Activity,销毁相关资源

光说了这些理论的东西是不够,只有亲自测试验证过了记忆才够深刻,下面是我测试验证的主要代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
public class LifeCycle_A_Activity extends Activity {
private final String TAG = getClass().getSimpleName();
private Button btn1;
private Button btn2;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle_a_layout);
btn1 = (Button) findViewById(R.id.btn_lifecycle);
btn2 = (Button) findViewById(R.id.btn_lifecycle2);
btn1.setText("跳转到LifeCycle_B_Activity(透明)");
btn2.setText("跳转到LifeCycle_C_Activity(非透明)");

btn1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
toAnotherActivity(LifeCycle_B_Activity.class);
}
});
btn2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
toAnotherActivity(LifeCycle_C_Activity.class);
}
});

Log.i(TAG, "LifeCycle----onCreate");
}

public void toAnotherActivity(Class<?> claxx) {
startActivity(new Intent(LifeCycle_A_Activity.this, claxx));
}

@Override
protected void onStart() {
super.onStart();
Log.i(TAG, "LifeCycle----onStart");
}

@Override
protected void onRestart() {
super.onRestart();
Log.i(TAG, "LifeCycle----onRestart");
}

@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "LifeCycle----onResume");
}

@Override
protected void onStop() {
super.onStop();
Log.i(TAG, "LifeCycle----onStop");
}

@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "LifeCycle----onPause");
}

@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "LifeCycle----onDestroy");
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("stateParam", 1);
Log.i(TAG, "LifeCycle----onSaveInstanceState,save value is:" + 1);
}

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
int value = savedInstanceState.getInt("stateParam");
Log.i(TAG, "LifeCycle----onRestoreInstanceState,restore value is:" + value);
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
Log.i(TAG, "LifeCycle----onWindowFocusChanged, focus is:" + hasFocus);
}
}

该Activity对应的布局文件代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical" >

<Button
android:id="@+id/btn_lifecycle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

<Button
android:id="@+id/btn_lifecycle2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

</LinearLayout>

Activity跳转后覆盖的透明与非透明的Activity代码及布局文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//透明的Activity,在注册Activity时需要添加theme属性
//android:theme="@android:style/Theme.Translucent"
public class LifeCycle_B_Activity extends Activity {
private Button btn;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle_b_layout);
btn = (Button) findViewById(R.id.btn_lifecycle);
btn.setText("当前为LifeCycle_B_Activity(透明)");
}
}

//非透明的Activity
public class LifeCycle_C_Activity extends Activity {
private Button btn;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lifecycle_b_layout);
btn = (Button) findViewById(R.id.btn_lifecycle);
btn.setText("当前为LifeCycle_C_Activity(非透明)");
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical" >

<Button
android:id="@+id/btn_lifecycle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

</LinearLayout>

很明显,上面的验证代码中我多写了三个方法onWindowFocusChangedonSaveInstanceStateonRestoreInstanceState,这三个方法都不属于Activity生命周期函数,只是这三个函数在Activity生命周期变化时,对于我们的应用开发还是紧密相关的,所以我给加进来一起看下他们的执行时机。

  1. onWindowFocusChanged:看名字就可以知道,这个函数是Activity窗体焦点发生变化时的回调,比如Activity在前台显示,被覆盖,手机截屏,按下Home键等等,都会触发该方法。再结合我上面生命周期过程验证结果,其实更容易理解,该函数只会在Activity是否前台显示发生变化时触发,也就是在onResumeonPause调用后触发该函数。当我们想在Activity初始化时获取某个特定组件的大小时,在onCreate中是无法获取的,因为这个时候Window对象还没有创建完成,这个时候,我们可以通过onWindowFocusChanged函数来获取指定组件的大小。

  2. onSaveInstanceState:`

    1. 当系统资源不足杀死Activity时会调用该函数。
    2. 当屏幕方向发生变化时也会调用该函数。
    3. 当Activity被覆盖或锁屏或按下Home键时都会调用该函数。该方法主要用于保存当前窗体各个视图组件View的状态信息,当然我们也可以手动保存一些临时变量以避免资源不足Activity被杀死或屏幕发生变化后无法恢复到之前状态。根据上面的生命周期过程验证发现onSaveInstanceState是在Activity由前台显示变为不显示时触发,也就是在onPause调用后触发该函数。这个也很容易理解,当Activity由前台显示变为后台显示时,只有先将当前的窗体各个视图组件状态保存起来,系统后续恢复起来才有依据才知道恢复到什么样子。
  3. onRestoreInstanceState:该函数与onSaveInstanceState相对的,它主要用于恢复用户保存的一些临时数据以及系统之前通过onSaveInstanceState保存的各个组件的状态信息。此方法目前经过验证只在屏幕方向发生变化时才会调用。系统资源不足杀死Activity后重新恢复创建Activity这种情况无法验证,这种情况是否执行待验证。

屏幕方向发生变化时验证如下结果如下图(在手机设置中先设置为自动旋转屏幕,在AndroidMainfest.xml中注册Activity时不要设置android:screenOrientation属性):

上面日志中清晰的记载了Activity销毁之前保存的临时变量通过onRestoreInstanceState可用获取得到。

write by laohu

2015年10月8日21:56:06


原创文章,转载请出处注明。

下面是我的个人公众号,欢迎关注交流

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×