Activity生命周期分析
- Activiy启动:onCreate() => onStart() => onResume()
2019-09-17 18:51:21.639 26091-26091/? D/LifeActivity: --------onCreate:
2019-09-17 18:51:21.714 26091-26091/? D/LifeActivity: --------onStart:
2019-09-17 18:51:21.716 26091-26091/? D/LifeActivity: --------onResume:
- Activity 进入后台 ( 按下Home 或启动新 Activity ): onPause() => onStop()
2019-09-17 19:36:10.457 29902-29902/com.fr.myapplication D/LifeActivity: --------onPause:
2019-09-17 19:36:10.929 29902-29902/com.fr.myapplication D/LifeActivity: --------onStop:
- Activity 返回前台: onRestart() => onStart() => onResume()
2019-09-17 19:36:15.411 29902-29902/com.fr.myapplication D/LifeActivity: --------onRestart:
2019-09-17 19:36:15.412 29902-29902/com.fr.myapplication D/LifeActivity: --------onStart:
2019-09-17 19:36:15.413 29902-29902/com.fr.myapplication D/LifeActivity: --------onResume:
- 锁屏: onPause() => onStop()
2019-09-17 19:36:10.457 29902-29902/com.fr.myapplication D/LifeActivity: --------onPause:
2019-09-17 19:36:10.929 29902-29902/com.fr.myapplication D/LifeActivity: --------onStop:
- 解锁: onRestart() => onStart() => onResume()
2019-09-17 19:40:09.387 29902-29902/com.fr.myapplication D/LifeActivity: --------onRestart:
2019-09-17 19:40:09.389 29902-29902/com.fr.myapplication D/LifeActivity: --------onStart:
2019-09-17 19:40:09.391 29902-29902/com.fr.myapplication D/LifeActivity: --------onResume:
- Activity A启动另一个Activity B时回调如下
Activity A的onPause() -> Activity B的onCreate() -> onStart() -> onResume() ->Activity A的onStop(); 特殊情况 : 当Activity B是透明主题或者DialogActivity时不会调用Activity A的onStop();
Activity生命周期回调方法
- onCreate() 首次创建 Activity 时调用。 您应该在此方法中执行所有正常的静态设置 — 创建视图、将数据绑定到列表等等。 系统向此方法传递一个 Bundle 对象,其中包含 Activity 的上一状态,不过前提是捕获了该状态 始终后接 onStart()。
- onRestart() 在 Activity 已停止并即将再次启动前调用。 始终后接 onStart() 在 Activity 已停止并即将再次启动前调用。 始终后接 onStart()
- onStart() 在 Activity 即将对用户可见之前调用。 如果 Activity 转入前台,则后接 onResume(),如果 Activity 转入隐藏状态,则后接 onStop()。
- onResume() 在 Activity 即将开始与用户进行交互之前调用。 此时,Activity 处于 Activity 堆栈的顶层,并具有用户输入焦点。 始终后接 onPause()。
- onPause() 当系统即将开始继续另一个 Activity 时调用。 此方法通常用于确认对持久性数据的未保存更改、停止动画以及其他可能消耗 CPU 的内容,诸如此类。 它应该非常迅速地执行所需操作,因为它返回后,下一个 Activity 才能继续执行。 如果 Activity 返回前台,则后接 onResume(),如果 Activity 转入对用户不可见状态,则后接 onStop()。
- onStop() 在 Activity 对用户不再可见时调用。如果 Activity 被销毁,或另一个 Activity(一个现有 Activity 或新 Activity)继续执行并将其覆盖,就可能发生这种情况。 如果 Activity 恢复与用户的交互,则后接 onRestart(),如果 Activity 被销毁,则后接 onDestroy()。
- onDestroy() 在 Activity 被销毁前调用。这是 Activity 将收到的最后调用。 当 Activity 结束(有人对 Activity 调用了 finish()),或系统为节省空间而暂时销毁该 Activity 实例时,可能会调用它。 您可以通过 isFinishing() 方法区分这两种情形。
Activity的4种状态
Running / Paused / Stopped / Killed
Running
Activity处于活动状态,此时Activity处于栈顶,是可见状态,可与用户进行交互。
Paused
当Activity失去焦点时,或被一个新的非全屏的Activity,或被一个透明的Activity放置在栈顶时,Activity就转化为Paused状态。此时Activity只是失去了与用户交互的能力,其所有的状态信息及其成员变量都还存在,只有在系统内存紧张的情况下,才有可能被系统回收掉。
Stopped
当一个Activity被另一个Activity完全覆盖时,被覆盖的Activity就会进入Stopped状态,此时它不再可见,但是跟Paused状态一样保持着其所有状态信息及其成员变量。
Killed
当Activity被系统回收掉时,Activity就处于Killed状态。
Activity生命周期流程图
异常情况下的生命周期分析
我们知道,Activity除了受用户操作所导致的正常的生命周期方法的调度,还有一些异常情况,比如当资源相关的系统配置发生改变以及系统内存不足时,Activity就可能被杀死。
1. 资源相关的系统配置发生改变导致Activity被杀死并重新创建
例如当前的Activity处于竖屏状态,如果突然旋转屏幕,由于系统配置发生了改变,在默认的情况下,Activity就会被销毁并且重新创建,当然我们可以阻止系统重新创建我们的Activity。
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(TEXT,text);
Log.d(TAG, "--------onSaveInstanceState: ");
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
text = savedInstanceState.getString(TEXT);
Log.d(TAG, "--------onRestoreInstanceState: ");
}
注意:系统只有在Activity异常终止的时候才会调用onSaveInstanceState和onRestoreInstanceState来储存和恢复数据,其他情况下不触发这个过程
2.资源内存不足导致低优先级的Activity被杀死
Activity按照优先级从高到低,可以分为以下三种
- (1) 前台Activity——正在和用户交互的Activity,优先级最高。
- (2) 可见但非前台的Activity——比如Activity中弹出一个对话框,导致Activity可见但位于后台无法和用户直接交互。
- (3) 后台Activity——已经被暂停的Activity,比如执行onStop,优先级最低。
当系统的内存不足时,系统会按照上述的优先级去杀死目标Activity所在的进程,并在后续通过onSaveInstanceState和onRestoreInstanceState来储存和恢复数据。
configChanges
在AndroidManifest.xml中设置configChanges属性的值可以使系统配置发生变化后,Activity不被重新创建,以达到和onSaveInstanceState和onRestoreInstanceState来储存和恢复数据一样的效果。
<activity android:name=".LifeActivity"
android:configChanges="orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
附上代码:
Activity部分
public class LifeActivity extends AppCompatActivity {
private static final String TAG = "LifeActivity";
private static final String TEXT = "text";
private EditText editText;
private String text;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "--------onCreate: ");
setContentView(R.layout.activity_life);
editText = findViewById(R.id.et_text);
text = String.valueOf(editText.getText());
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG, "--------onStart: ");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG, "--------onPause: ");
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG, "--------onStop: ");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG, "--------onResume: ");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG, "--------onRestart: ");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG, "--------onDestroy: ");
}
public void click(View view) {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(TEXT,text);
Log.d(TAG, "--------onSaveInstanceState: ");
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
text = savedInstanceState.getString(TEXT);
Log.d(TAG, "--------onRestoreInstanceState: ");
}
}
其中的MainActivity,为页面内跳转测试当前生命周期而存在,可为任意一个Activity此处就不贴出代码了
布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Activity学习.LifeActivity">
<Button
android:id="@+id/bt_click"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点击跳转"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
tools:ignore="HardcodedText"
android:onClick="click"/>
<EditText
android:id="@+id/et_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
android:hint="输入内容"
app:layout_constraintTop_toBottomOf="@id/bt_click"
android:inputType="text"
android:imeOptions="actionDone"/>
</androidx.constraintlayout.widget.ConstraintLayout>