- 安卓每个活动在其生命周期中最多可能有四种状态:
- 运行状态:
- 当一个活 动 位于返回 栈 的 栈顶时 , 这时 活 动 就 处 于运行状 态。
- 暂停状态:
- 当一个活 动 不再 处 于 栈顶 位置,但仍然可 见时 , 这时 活 动 就 进 入了 暂 停状 态 。你可能会 觉得既然活动 已 经 不在 栈顶 了, 还 怎 么 会可 见 呢? 这 是因 为 并不是 每 一个活 动 都会占 满 整个 屏幕的,比如对话 框形式的活 动 只会占用屏幕中 间的部分区域。
- 停止状态:
- 当一个活 动 不再 处 于 栈顶 位置,并且完全不可 见 的 时 候,就 进 入了停止状 态 。系 统 仍然会为这种活 动 保存相 应 的状 态 和成 员变 量,但是 这 并不是完全可靠的,当其他地方需要内存时, 处 于停止状 态 的活 动 有可能会被系 统 回收。
- 销毁状态:
- 当一个活 动 从返回 栈 中移除后就 变 成了 销毁 状 态 。系 统 会最 倾 向于回收 处 于 这种 状 态 的活动,从而保 证 手机的内存充足。
Activity类中定义了7个回调方法,覆盖了活动生命周期的每一个环节:
- onCreate() 。每个活动中我们都会重写这个方法,它会在活动第一次被创建的时候调用。在这个方法中完成活动的初始化操作,比如说加载布局、绑定事件等。
- onStart() 。这个方法在活动由不可见变为可见的时候调用。
- onResume() 。这个方法在活动准备好和用户进行交互的时候调用。此时的活动一定位于返回栈的栈顶,并且处于运行状态。
- onPause() 。这个方法在系统准备去启动或者恢复另一个活动的时候调用。我们通常会在这个方法中将一些消耗CPU的资源释放掉,以及保存一些关键数据,但这个方法的执行速度一定要快,不然会影响到新的栈顶活动的使用。
- onStop() 。这个方法在活动完全不可见的时候调用。它和onPause() 方法的主要区别在于,如果启动的新活动是一个对话框式的活动,那么onPause() 方法会得到执行,而onStop() 方法并不会执行。
- onDestroy() 。这个方法在活动被销毁之前调用,之后活动的状态将变为销毁状态。
- onRestart() 。这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新启动了。
以上 7 个方法中除了 onRestart() 方法,其他都是两两相 对 的,从而又可以将活 动 分 为 3 种 生存期。
- 完整生存期 。活动在onCreate() 方法和onDestroy() 方法之间所经历的,就是完整生存期。一般情况下,一个活动会在onCreate() 方法中完成各种初始化操作,而在onDestroy() 方法中完成释放内存的操作。
- 可见生存期 。活动在onStart() 方法和onStop() 方法之间所经历的,就是可见生存期。在可见生存期内,活动对于用户总是可见的,即便有可能无法和用户进行交互。我们可以通过这两个方法,合理地管理那些对用户可见的资源。比如在onStart() 方法中对资源进行加载,而在onStop() 方法中对资源进行释放,从而保证处于停止状态的活动不会占用过多内存。
- 前台生存期 。活动在onResume() 方法和onPause() 方法之间所经历的就是前台生存期。在前台生存期内,活动总是处于运行状态的,此时的活动是可以和用户进行交互的,我们平时看到和接触最多的也就是这个状态下的活动。
实践项目:
主活动布局:
<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"
android:onClick="startNormalActivity"/>
<Button
android:id="@+id/start_dialog_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start DialogActivity"
android:onClick="startDialogActivity"/>
</LinearLayout>
NormalActivity布局:
<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>
子活动DialogActivity布局:
<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>
AndroidManifest.xml内容:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.activitylifecycletest">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".DialogActivity"
android:theme="@style/Theme.AppCompat.Dialog">
</activity>
<activity android:name=".NormalActivity" />
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
两个子活动的代码不需要再重新编写,用自动生成的即可:
public class NormalActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.normal_activity);
}
}
public class DialogActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dialog_activity);
}
}
主活动代码:
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "+++++++++++++++++++++++++");
Log.d(TAG,"onCreate:这个方法中完成活动的初始化操作");
setContentView(R.layout.activity_main);
}
public void startNormalActivity(View v){
Intent intent = new Intent(MainActivity.this,NormalActivity.class);
startActivity(intent);
}
public void startDialogActivity(View v){
Intent intent = new Intent(MainActivity.this,DialogActivity.class);
startActivity(intent);
}
//onStart() 活动由不可见变为可见
@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: 这个方法在活动由停止状态变为运行状态之前调用,也就是活动被重新" +
"启动了。");
}
}
首次运行之后虚拟机界面:
此时我们用筛选器查看TAG即MainActivity标签的内容为:
可以看到,当MainActivity第一次被创建时会依次执行onCreate() 、onStart() 和 onResume() 方法。
当我们点击第一个按钮startNormalActivity后,虚拟机的界面为:
此时再查看日志发现又执行了此onPause() 和onStop() 方法:
由于NormalActivity已经把MainActivity完全遮挡住,因此onPause() 和onStop() 方法都会得到执行。
然后我们再按下back键返回MainActivity,此时我们再查看日志发现onRestart() 方法会得到执行,之后又会依次执行onStart() 和onResume() 方法。
接着再点第二个按钮startDialogActivity,此时虚拟机的界面为:
这时活动就处于暂停状态,可以通过打印的日志看到,只有onPause() 方法得到了执行,onStop() 方法并没有执行,这是因为DialogActivity并没有完全遮挡住MainActivity,此时MainActivity只是进入了暂停状态,并没有进入停止状态。
再按一下back键,此时只有onResume() 方法会得到执行:
再按一下back键退出程序,程序会依次会执行onPause() 、onStop() 和onDestroy() 方法,最终销毁MainActivity。
这就是一个完整的生命周期。