三流码奴的自我救赎

0%

Activity生命周期

作为Android四大组件中最为基础的组件,Ativity承担着应用和用户交互的基本任务。

Activity是应用与用户进行交互的单一焦点,基本所有Activity都与用户进行交互。所以Activity负责创建一个Window,可以通过setContentView方法加载UI。
Activity经常以全屏窗口向用户展示用户界面,或者可以通过在theme中设置windowIsFloatingflag使之变为一个悬浮窗口,还可以启用多窗口模式,或将窗口嵌入其他窗口中。

Activity在系统中以activity stack的形式进行管理。当一个新的activity启动的时候,一般情况下会被放入当前activity stack的栈顶,成为running activity。一般情况下前一个activity依旧会存于与栈中,但是只要栈顶activity还存在就不会回到前台。
注意在屏幕上看到的Activity可能属于不同的activity stack

Activity的生命周期方法

老生常谈的问题,Activity的常用生命周期方法一共有7个:

1
2
3
4
5
6
7
8
9
public class Activity extends ApplicationContext { 
protected void onCreate(Bundle savedInstanceState);
protected void onStart();
protected void onRestart();
protected void onResume();
protected void onPause();
protected void onStop();
protected void onDestroy();
}

其中除了onRestart(),其余6个生命周期方法均两两成为一对:

1
2
3
onCreate() -> onResume()
onStart() -> onStop()
onResume() -> onPause()

给出Activity的生命周期图导航图:
activity_lifecycle
一张看了无数遍的图,但是其中的细节是经常容易忽略的:

  • onStop()方法是否执行取决于该activity是否可见。
  • onRestart()方法实际上是和onCreate()方法互补的,activity从无到有的情况回调用onCreate()方法,而重新启动(还没有被销毁)的activity重新回到前台会调用到onRestart()方法。

Activity的生命周期状态

根据activity的7个主要生命周期方法,将activity的生命周期状态归纳为3种:

  1. **entire lifrtime :**对应onCreate()onDestory()中间的任意时刻和状态,此状态区间内不一定对用户可见。
  2. **visible lifrtime :**对应onStart()onStop()中间的任意时刻和状态,此状态区间内对用户可见,但不一定可以进行交互。
  3. **foreground lifrtime :**对应onResume()onPause()中间的任意时刻和状态,此状态区间内对用户可见,并且可交互。

Activity的非正常退出(系统kill)

前面提到过,activity在正常情况下退出会调用finish()方法,调用完整的销毁生命周期:onPause() -> onStop() -> onDestory(),但当activiy不可见的时候,可能随时被系统kill以释放内存,这个时候并不会经历完成整的销毁生命周期,如下表所示:

方法 调用时机 是否可以被kill
onCreate() activity创建 No
onStart() activity对用户可见 No
onResume() activity可交互 No
onPause() activity不可交互 Android 3之后不能被kill
onStop() activity不可见 Yes
onDestory() activity销毁 Yes

其中我们可以看到onPause()方法在Android3之后不再可被系统kill掉,也就是说,如果需要持久化用户数据以便后续使用或恢复状态,在onPause()中全部完成最为保险。

而自从Android P开始,用于保存临时数据的回调onSaveInstanseState()延迟到onStop()结束之后调用,这也就意味着在更晚的生命周期方法onStop()之后进行数据保存完成fragment transaction也是安全的。

Configuration Changes导致的生命周期变化

Configuration指的是由Configuration类所定义的属性。
当这个设置发生变化的时候,整个应用的UI都需要同步进行更新以适应新的配置。Activity拥有响应``configuration chages的回调。
Configuration Changes包括如下一些情况:

  • 屏幕旋转
  • 变更语言
  • 其他一些情况
    当出现configuration changes的时候会导致当前的activity通过正常的生命周期销毁。若果这个activity处于visible状态,则onDestory()执行完之后会立刻重建,onCreate(Bundle)中传入的savedInstanceState就由销毁之前的onSaveInstanceState()回调生成。

应用中可以通过设置android:configChanges来避免因configuration changes导致的activity重建,此时会调用回调方法onConfigurationChanged()来适配。
注意:
若该变化影响到了配置之外的属性,则不会调用onConfigurationChanged()回调,会直接对activity进行重建。

ActivityResult影响生命周期

一般情况下我们通过startActivity()方法启动一个activity,但我们需要被启动的activity返回一个结果给前一个activity时,就需要使用到startActivityForResult()方法。
当被启动的activity还存在时,就可以调用setResult()方法将结果返回给启动它的activity,而启动它的activity会调用到onActivityResult()方法接收数据。
需要注意的是onActivityResult()的调用是在整个activity生命周期之前的,也就是说调用顺序是onActivityResult() -> onRestart() -> onStart() -> onResume()

Activity进程生命周期

对于Android系统来说每个application process应该尽可能维持更长时间的存活,但实际上有很多时候都不得不杀死老进程来释放内存资源。系统决定销毁哪个process与它当前是否正在与用户进行交互是密切相关的。

  • **Foreground Activity:**如果一个Activity在前台(位于栈顶),则该activity的状态为activerunning。这个状态的activity通常是正在与用户发生交互的。这种情况下如果不出现OOM系统不回去kill这个进程。
  • **Visiable Activity:**如果一个activity 失去焦点但仍然对用户可见,则该activity的状态为visible。可能会由一个non-full-sized或者透明的activity在原activity之上获得焦点导致。这种activity一定是alive的。这种情况下如果内存不足以保持foreground activity存活,则会被系统kill。
  • **Background Activity:**当一个activity对用户完全不可见的时候,状态为stoppedhidden,当系统内存不足的时候,可以以call finishkill process的形式终结一个activity,使它的状态变为destoryed。回收之前回调用onSaveInstanceState(Bundle)方法对用户状态进行保存,当用户回到被杀死的界面时,在onCreate()方法对其状态进行恢复。
  • **Empty Process:**这里要着重强调一下,空进程并不代表进程中没有执行任何任务。空进程的定义是,在进程中没有任何一个存活的activity,service或者broadcastReciever。所以如果需要执行后台任务的话一定要将任务放到四大组件中。