活动的生命周期
掌握活动的生命周期对任何 Android开发者来说都非常重要,当你深入理解活动的生命 周期之后,就可以写出更加连贯流畅的程序,并在如何合理管理应用资源方面,你会发挥的 游刃有余。你的应用程序将会拥有更好的用户体验。
一 返回栈
1. 定义: Android是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的活动 的集合这个栈也被称作返回栈(Back Stack)。
2. 栈顶:存放刚启动的一个新的活动。(当我们 按下 Back键或调用 finish()方法去销毁一个活动时,处于栈顶的活动会出栈,这时前一个入 栈的活动就会重新处于栈顶的位置。系统总是会显示处于栈顶的活动给用户。)
二 活动状态
1.运行状态:活动位于返回栈的栈顶时(系统最不愿意回收的 就是处于运行状态的活动,因为这会带来非常差的用户体验。)
2.暂停状态:当一个活动不再处于栈顶位置,但仍然可见时(比如某个活动上面新开了个对话框活动该活动就是暂停活动-系统也不愿意去回收这 种活动。)
3.停止状态:当一个活动不再处于栈顶位置,并且完全不可见的时候,就进入了停止状态。(系统 仍然会为这种活动保存相应的状态和成员变量,但很容易被回收)
4.销毁状态:当一个活动从返回栈中移除后就变成了销毁状态(系统会最倾向于回收处于这种状 态的活动,从而保证手机的内存充足。)
三 创建活动的生存期
1.
onCreate() :它会在活动 第一次被创建的时候调用用于加载布局、绑定事件等。
2.
onStart():这个方法在活动由不可见变为可见的时候调用。
3.
onResume():这个方法在活动准备好和用户进行交互的时候调用。此时的活动一定位于返回栈的 栈顶,并且处于运行状态。
4.
onPause(): 这个方法在系统准备去启动或者恢复另一个活动的时候调用。
5.
onStop(): 这个方法在活动完全不可见的时候调用。-----(如 果启动的新活动是一个对话框式的活动,那么 onPause()方法会得到执行,而 onStop() 方法并不会执行。)。
6.
onDestroy():这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态。
7.
onRestart():活动被重新启动时调用。
完整生存期:【 onCreate()~ onDestroy()】之间。
可见生存期:【 onStart()~ onStop()】之间。活动对于用户总是可见的!{我们可以通过这两 个方法对资源进行加载和释放}
前台生存期:【 onResume()~ onPause()】之间。活动总是处于运行状态的!{可以和用户进行相互。}
四 体验活动的生命周期
1.新建一个 ActivityLifeCycleTest项目默认生成主活动,和布局,修改布局文件activity_main.xml,重新定制我们主活动的布局。
//加入了两个按钮。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/start_normal_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start NormalActivity" />
<Button
android:id="@+id/start_dialog_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start DialogActivity" />
</LinearLayout>
2.我们还需要分别再创建两个子活动,NormalActivity 和 DialogActivity。
- 新建 normal_layout.xml文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is a normal activity"
/>
</LinearLayout>
- 新建一个 dialog_layout.xml文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This is a dialog activity"
/>
</LinearLayout>
- 新建 DialogActivity继承自 Activity加载了 dialog_layout这个布局
public class DialogActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.dialog_layout);
}
}
- 新建 NormalActivity继承自 Activity加载了 normal_layout这个布局。
public class NormalActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.normal_layout);
}
}
- 在 AndroidManifest.xml注册时,将活动DialogActivity设 成对话框式;将NormalActivity设为普通的活动。
<activity android:name=".NormalActivity" >
</activity>
<activity android:name=".DialogActivity" android:theme="@android:style/
Theme.Dialog" >
</activity>
3.最后修改 MainActivity中的代码。第一个按钮会启动 NormalActivity,点击第二个按钮会启动 DialogActivity。
public class MainActivity extends Activity {
public static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
Button startNormalActivity = (Button) findViewById(R.id.start_ normal_activity);
Button startDialogActivity = (Button) findViewById(R.id.start_ dialog_activity);
startNormalActivity.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, NormalActivity.class);
startActivity(intent);
}
});
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, "onRestart");
}
}
- 然后运行程序: 执行:
onCreate()
onStart()
onResume() 方法
- 然后点击第一个按钮启动 NormalActivity:(由于 NormalActivity已经把 MainActivity完全遮挡住,)
执行:
onPause()
onStop()
- 然后按下 Back键返回 MainActivity(由于之前 MainActivity已经进入了停止状态)
执行:
onRestart()
onStart()
onResume()
- 然后再点击第二个按钮,启动 DialogActivity(DialogActivity并没有完全遮挡住 MainActivity)
执行:
onPause()
- Back键返回 MainActivity
执行:
onResume()
- 最后在 MainActivity按下 Back键退出程序
执行:
onPause()
onStop()
onDestroy()
五:活动被回收了问题
onSaveInstanceState()回调方法:我们可以通过这个方法来解决活动被回收时临时数据得不到保存的问题。
@Override
/* Bundle 类型的参数,使用 putString()方法保存字符串,使用 putInt()方法保存整型数据
每个保存方法需要传入两个参数,第一个参数是键,用于后面从 Bundle中取值, 第二个参数是真正要保存的内容*/
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
String tempData = "Something you just typed";
outState.putString("data_key", tempData);
}
//使用的 onCreate()方法其实也有一个 Bundle类型的参数,将数据取出即可。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
String tempData = savedInstanceState.getString("data_key");
Log.d(TAG, tempData);
}
…… }