本文主要有以下几点:
- 什么叫返回栈?
- Activity 的四种状态
- Activity 的生命周期
1. 什么叫返回栈?
1)首先介绍什么叫栈。栈(Stack),是先进后出(FIFO,First In First Out)的数据结构,即最先进来的最后出去;而与栈相反的是队列,队列的是一种后进先出(Last In First Out)的数据结构,即最后进来的最先出去。大家可以把可以把栈想象成一个瓶子,通常瓶子只有一个口子(即是入口又是出口),我们往瓶子里扔石头,最先进来的石头被压在瓶底,最后进来的石头在瓶子的最上面,瓶底的石头想要出去,就得等最上面的石头都出去了,它才能出去;而可以把队列想象成一根两头都通的水管,一头是入口,一头是出口,同样水管里塞石头,那么最先进去的石头肯定是最先出来的;
2)而返回栈则是用于存放 Activity 的集合,每当启动一个 Activity 的时候,它就会进入返回栈,并且处于栈顶的位置(这个 Activity 处于前台);当销毁一个 Activity 的时候,就是把处于栈顶的 Activity 弹出去(即出栈),假设 A 原本处于栈顶,B 在 A 之下,由于 A 出栈了,这时 B 就会重新处于栈顶;而用户看到的就是处于栈顶的 Activity;
3)下图取自于官方文档:
从图中可以看出,原本栈中只有一个 Activity —— Activity 1,当启动第二个 Activity 时,这时原本处于栈顶的 Activity 1 就会被压到栈底,而处于栈顶的是 Activity 2,再启动第三个 Activity,这时 Activity 2 也被压到栈底,但它还是在 Activity 1 的上面,这时从返回栈中移除 Activity 3,Activity 2 将重新回到栈顶。
2. Activity 的四种状态
1)运行状态
当一个 Activity 处于前台时,即处于栈顶时,它是活动或者运行的状态。
2)暂停状态
当一个 Activity 失去焦点但仍然可见时,该 Activity 处于暂停状态(例如,在一个 Activity 上弹出一个对话框,该对话框并不铺满屏幕,原先的 Activity仍然被用户能看到)。一个处于暂停状态的 Activity 仍然是完全存活的(它会保存之前的状态和成员变量),但在内存极低的情况下会被系统杀死。
3)停止状态
但一个 Activity 完全被另一个 Activity 隐藏时,该 Activity 处于停止状态(即该 Activity 不再处于栈顶,并且不对用户来说可见时)。处于停止状态的 Activity 会保存之前的状态和成员变量,但在系统内存不够时,有可能被系统杀死(这种概率比处于暂停状态的 Activity 高)。
4)销毁状态
当一个 Activity 被移出返回栈时,它就处于销毁状态。处于销毁状态的 Activity 最有可能被系统回收。
3. Activity 的生命周期
Activity 有以下七个回调方法,这七个方法会在 Activity 生命周期的不同时刻分别被调用:<code>onCreate()</code>、<code>onStart()</code>、<code>onRestart()</code>、<code>onResume()</code>、<code>onPause()</code>、<code>onStop()</code>、<code>onDestroy()</code>。
1)七个回调方法详解
方法名称 | 描述 | 是否可被杀死 | 下一个被调用的方法 |
---|---|---|---|
onCreate() | Activity 第一次创建时调用,应当在此方法内完成初始化操作,如:加载布局、初始化布局中的控件等。 | 否 | onStart() |
onStart() | Activity 由不可见变为可见时调用。当 Activity 返回前台时,onResume() 方法会在此方法执行之后被调用;当 Activity 变为不可见时,onStop() 方法会在此方法执行之后被调用。 | 否 | onResume()/onStop() |
onRestart() | Activity 由停止状态变为运行状态之前调用,即 Activity 重新启动时调用。 | 否 | onStart() |
onResume() | Activity 即将与用户交互之前被调用。此时 Activity 处于 Activity 堆栈的栈顶。 | 否 | onPause() |
onPause() | 启动或恢复另一个 Activity 时被调用。应当在此方法内保存一些关键数据、释放一些消耗 CPU 的资源、停止动画等。此方法应当被迅速执行,因为只有该方法执行完成之后,下一个 Activity 才能被执行。当 Activity 返回前台时,onResume() 方法会在此方法执行之后被调用;当 Activity 变为不可见时,onStop() 方法会在此方法执行之后被调用。 | Android 3.0 之前可以 | onResume()/onStop() |
onStop() | Activity 不再可见时被调用。当 Activity 即将与用户的交互时,onRestart() 方法会在此方法执行之后被调用;当 Activity 被销毁时,onDestroy() 方法会在此方法执行之后被调用。 | 是 | onRestart()/onDestroy() |
onDestroy() | Activity 被销毁之前最后被调用的方法。应当在此方法内释放内存。 | 是 | - |
2)Activity 生命周期的三个生存期(循环嵌套)
1. 完整生存期
- Activity 的完整生存期是指在 <code>onCreate()</code> 方法第一次被调用和 <code>onDestroy()</code> 方法最后一次被调用之间的时间段;
- 应当在 <code>onCreate()</code> 方法内完成初始化操作, 并在 <code>onDestroy()</code> 方法内释放内存。
2. 可见生存期
- Activity 的可见生存期是指在 <code>onStart()</code> 方法被调用和 <code>onStop()</code> 方法被调用之间的时间段;
- 在可见生存期内,Activity 是可见的,即使该 Activity 不再前台和无法与用户交互;
- 在 Activity 的整个生命周期,当 Activity 在对用户可见和隐藏两种状态中交替变化时,系统可能会多次调用 <code>onStart()</code> 方法和 <code>onStop()</code> 方法。
3. 前台生存期
- Activity 的前台生存期是指在 <code>onResume()</code> 方法被调用和 <code>onPause()</code> 方法被调用之间的时间段;
- 在前台生存期内,Activity 处于运行状态,位于屏幕上其他所有 Activity 之上,能与用户进行交互。
下图取自官方文档,描述了 Activity 的生命周期:
3)实例
上面讲了那么多,下面我们通过一个实例来更好地感受一下。我们来做这样一个程序:主界面上有两个按钮,按钮 A 用于跳转到另一个 Activity,按钮 B 用于弹出一个对话框。
1. 首先是主界面:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="16dp"
tools:context=".MainActivity">
<Button
android:id="@+id/btn1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="启动第二个Activity" />
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="打开对话框" />
</LinearLayout>
效果:
Java 代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private Button btn1;
private Button btn2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v(TAG, "onCreate");
// 初始化布局中的控件
btn1 = (Button) findViewById(R.id.btn1);
btn2 = (Button) findViewById(R.id.btn2);
// 设置按钮的监听器
btn1.setOnClickListener(this);
btn2.setOnClickListener(this);
}
@Override
protected void onStart() {
super.onStart();
Log.v(TAG, "onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.v(TAG, "onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.v(TAG, "onPause");
}
@Override
protected void onStop() {
super.onStop();
Log.v(TAG, "onStop");
}
@Override
protected void onRestart() {
super.onRestart();
Log.v(TAG, "onRestart");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.v(TAG, "onDestroy");
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn1:
Intent intent1 = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent1);
break;
case R.id.btn2:
Intent intent2 = new Intent(MainActivity.this, DialogActivity.class);
startActivity(intent2);
break;
default:
break;
}
}
}
2. 第二个界面:
activity_second.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context=".SecondActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="欢迎来到第二个Activity"
android:gravity="center_horizontal"/>
</RelativeLayout>
Java 代码:
/**
* Created by Monkey.C on 2016/6/24.
*/
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
}
}
3. 对话框:
activity_dialog.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context=".DialogActivity">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="这是一个对话框" />
</RelativeLayout>
Java 代码:
/**
* Created by Monkey.C on 2016/6/24.
*/
public class DialogActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dialog);
}
}
4. AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="net.monkeychan.activitytest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 第二个 Activity -->
<activity android:name=".SecondActivity"/>
<!-- 设置 Activity 为 对话框样式 -->
<activity android:name=".DialogActivity" android:theme="@style/Theme.AppCompat.Dialog"/>
</application>
</manifest>
5. 效果演示:
1. 首先运行程序:
此时的 logcat:
可以看到 MainActivity 被创建了。
2. 点击主页键,此时的 logcat:
3. 在多任务列表中找到程序,点击它,返回程序:
此时的 logcat:
4. 点击返回键,退出程序,此时的 logcat:
可以看到此时 MainActivity 被销毁了。
5. 让我们再次运行程序,此时的 logcat:
可以看到 MainActivity 被重新创建。
6. 点击按钮,启动第二个 Acitivty:
此时的 logcat:
可以看到,MainActivity 并未销毁。
7. 点击按钮,返回第一个 Acitivty,此时的 logcat:
8. 这时点击第二个按钮,弹出对话框:
此时的logcat:
可以看到只执行了 <code>onPause()</code> 方法,而没有执行 <code>onStop()</code> 方法。
9. 点击返回键,使 MainActivity 回到前台,此时的 logcat:
整个完整的操作过程:
以上就是 Activity 的生命周期。
源码下载:点这里(密码:ccsb)
参考资料: