Activity生命周期

Activity生命周期的回调方法

onCreate()

  • 何时:Activity正在被创建。

  • 作用:进行初始化工作,如setContentView(界面资源)、初始化Activity所需数据。

  • 注意:此方法的传参Bundle为该Activity上次被异常情况销毁时保存的状态信息。

onRestart()

  • 何时:Activity正在重新启动。当前Activity从不可见重新变为可见。

onStart()

  • 何时:Activity正在被启动。

  • 注意:此时Activity已可见,但还不在前台,还无法和用户交互。

onResume()

  • 何时:Activity已在前台

onPause()

  • 何时:Activity正在停止。当前Activity已不在前台

  • 作用:你需要保存更改到持久数据、停止一些动画、停止一些耗时CPU操作等。

  • 注意:此方法不可做耗时操作。onPause()必须先执行完,新Activity的onResume()才会执行。

onStop()

  • 何时:Activity即将停止。当前Activity已不可见

  • 作用:在此方法中,可做一些稍微重量级的回收工作,如:取消网络连接、注销广播接收器等。

onDestroy()

  • 何时:Activity即将被销毁。

  • 作用:做回收工作和最终的资源释放。

Activity生命周期的切换过程

Activity生命周期的切换过程

  • 第一次启动,回调如下:onCreate -> onStart -> onResume

  • 当用户打开新的Activity时,回调如下:A onPause -> B onCreate -> B onStart -> B onResume -> A onStop。注意,若新的Activity采用了透明主题,那么当前Activity不会回调onStop

  • 当用户再次回到原Activity时,回调如下:onRestart -> onStart -> onResume

  • 当前单一Activity在前台,用户按back键时,回调如下:onPause -> onStop -> onDestroy

  • 当前单一Activity在前台,用户按Home键/锁屏时,回调如下:onPause -> onStop

Activity生命周期的各阶段

完整生命周期

Activity在onCreate()onDestroy()之间所经历的。

onCreate()中完成各初始化操作;在onDestroy()中释放资源。

可见生命周期

Activity在onStart()onStop()之间所经历的。

活动对于用户是可见的,但仍无法与用户进行交互。

前台生命周期

Activity在onResume()onPause()之间所经历的。

活动可见,且可交互。

异常的生命周期分析

当资源相关的系统配置发生改变导致Activity被杀死并重建。

当内存不足时,系统会杀死低优先级的Activity。

Activity的优先级

Activity按照优先级从高到低,可分为如下三种:

  1. 前台Activity —— 正在和用户交互,优先级最高。

  2. 可见但不在前台的Activity —— 比如Activity中有弹窗,导致其可见但不在前台,无法与用户交互。

  3. 后台Activity —— 已被停止的Activity,比如执行onStop,优先级最低。

当系统内存不足时,会按照Activity优先级从低到高去杀死目标Activity所在的进程。

若一个进程没有四大组件在执行,那么这个进程将很快被系统杀死。

onSaveInstanceState()onRestoreInstanceState()

当出现异常情况时,首先,Activity会被销毁,系统会回调其onPause() -> onStop() -> onDestroy(),同时也会调用onSaveInstanceState()来保存当前Activity的状态。

注意,onSaveInstanceState()onStop()之前调用,它与onPause()没有既定的时序关系。

接着,如果Activity能被重新创建,系统会回调其onCreate() -> onStart() -> onResume(),同时会将上次异常终止时保存的状态传递onRestoreInstanceState()onCreate()

注意,onRestoreInstanceState()onStart()之后被调用

在Activity被销毁前,系统会默认为我们保存该Activity的视图结构,并且在Activity重建后恢复这些视图结构,比如:文本框中用户输入的数据、列表滚动的位置等。

其实,和Activity一样,每个View都有onSaveInstanceState()onRestoreInstanceState(),而且官方View组件都有默认的实现。

保存View层次结构的工作流程是:

  1. Activity调动onSaveInstanceState()去保存数据。

  2. 然后Activity会委托Window去保存数据。

  3. Window再委托它的顶级ViewGroup去保存数据。

  4. 顶级ViewGroup再一一调用它的子视图View的onSaveInstanceState(0来保存数据。

而恢复View层次结构的工作流程与上面类似,也是上层委托下层,不同的是调用onRestoreInstanceState()

onConfigurationChanged()

当系统配置发生改变后,Activity会被销毁且重新创建。

系统配置中有很多内容,若当某项内容发生改变后,我们不想系统重新创建Activity,可给<Activity>中的configChanges属性赋予对应值。之后当指定的系统配置项发生改变时,Activity不会被重新创建,系统仅仅回调其void onConfigurationChanged(Configuration newConfig);

android:configChanges="orientation|keyboardHidden|locale"
1
系统配置项 含义
mcc SIM卡唯一标识IMSI中的国家代码发生改变,三位数字。
中国为460。
mnc SIM卡唯一标识IMSI中的运营商代码发生改变,两位数字。
中国移动TD系统为00,联通为01,电信为03。
locale 设备的本地位置发生改变。
如切换了系统语言。
touchscreen 触摸屏发生改变。
keyboard 键盘类型发生改变。
比如用户使用了外接键盘。
keyboardHidden 键盘的可访问性发生改变。
比如用户调出了键盘。
navigation 系统导航方式发生改变。
如采用了轨迹球导航。
screenLayout 屏幕布局发生改变。
如用户激活了另一个显示设备。
fontScale 系统字体缩放比例发生改变。
uiMode 用户界面模式发生改变。
如开启了夜间模式(API8添加)。
orientation 屏幕方向发生改变。
如旋转手机屏幕。
screenSize 屏幕的尺寸信息发生改变。
minSdkVersiontargetSdkVersion都低于13时,此项不生效。
smallestScreenSize 设备的实际物理屏幕尺寸发生改变,这个项和屏幕的方向没有关系。
比如用户切换到外部的显示设备上。
minSdkVersiontargetSdkVersion都低于13时,此项不生效。
layoutDirection 布局方向发生改变。(API17添加)

利用Fragment来保存和恢复

onSaveInstanceState(Bundle)中的Bundle类型变量,只能保存少量的数据,对于Bitmap等大数据则无能为力。此时可利用Fragment来进行大量数据的保存与恢复。

用于数据保护与数据的Fragment需要满足以下条件:

  • 此Fragment必须是空视图,即不实现onCreateView()或该方法返回null。

  • 重写此Fragment的onCreate(),并在其内部调用Fragment#setRetainInstance(true);

  • 声明需要保存的数据对象,并提供getter和setter。

public class RetainedFragment extends Fragment {
    // 需要保存的数据
    private Bitmap data;  
      
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setRetainInstance(true);  
    }  
  
    public void setData(Bitmap data) {  
        this.data = data;  
    }  
  
    public Bitmap getData() {  
        return data;  
    }  
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  • 将RetainedFragment应用到Activity上。
public class FragmentRetainDataActivity extends Activity {
    private static final String DATA_FRAGMENT_TAG = "data";
    private RetainedFragment dataFragment;
    private Bitmap mBitmap;
    
    @Override  
    public void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_xxx);   
    
        // 寻找上次创建过的RetainedFragment。若无,则创建并添加。
        FragmentManager fm = getFragmentManager();  
        dataFragment = (RetainedFragment) fm.findFragmentByTag(DATA_FRAGMENT_TAG);   
        if (dataFragment == null) { 
            dataFragment = new RetainedFragment();  
            fm.beginTransaction().add(dataFragment, DATA_FRAGMENT_TAG).commit();  
        }  
         
        initData();
    }
    
    @Override  
    public void onDestroy() {
        super.onDestroy();
        // 保存数据
        dataFragment.setData(mBitmap);  
    }
    
    private void initData() {
        mBitmap = collectMyLoadedData();
        if(mBitmap == null) {
            // 数据未被创建过
        }
    }
    
    private Bitmap collectMyLoadedData() {  
        return dataFragment.getData();  
    }
}
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

onRetainNonConfigurationInstance()

由于设备配置改变导致Activity重建,在Activity销毁前,系统会调用它的onRetainNonConfigurationInstance(),可以保存任何类型的对象。

在Activity重建之后,可以调用getLastNonConfigurationInstance()来获取之前保存的对象。

FragmentActivity在onCreate(Bundle savedInstanceState)中调用getLastNonConfigurationInstance()获取之前保存的信息,如ViewModelStore对象。

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    // ...
    NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance();
    if (nc != null) {
        mViewModelStore = nc.viewModelStore;
    }
    // ...
}
1
2
3
4
5
6
7
8
9

FragmentActivity重写父类Activity的onRetainNonConfigurationInstance()以在销毁(因设备配置改变导致)前保存自定义数据、ViewModelStore对象和各Fragment等信息。

而且,FragmentActivity把onRetainNonConfigurationInstance()声明为final,并提供一个新定义的onRetainCustomNonConfigurationInstance()给子类重写来保存自定义数据。

@Override
public final Object onRetainNonConfigurationInstance() {
    if (mStopped) {
        doReallyStop(true);
    }
    
    Object custom = onRetainCustomNonConfigurationInstance();

    FragmentManagerNonConfig fragments = mFragments.retainNestedNonConfig();

    if (fragments == null && mViewModelStore == null && custom == null) {
        return null;
    }

    NonConfigurationInstances nci = new NonConfigurationInstances();
    nci.custom = custom;
    nci.viewModelStore = mViewModelStore;
    nci.fragments = fragments;
    return nci;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20