Activity 知识梳理(1) Activity生命周期

1、概述

学习Activity生命周期,首先咱们要明白,学习它的目的不只在于要知道有哪些生命周期,而是在于明白各回掉函数调用的时机,以便在合适的时机进行正确的操做,如初始化变量、页面展现、数据操做、资源回收等。平时的工做习惯都是,onCreate(xxx)初始化,onResume()注册、拉取数据,onPause()反注册,onDestroy()释放资源,这篇文章总结了一些和关键生命周期相关联的一些要点。java

2、金字塔模型

Activity 生命周期金字塔模型.png
在官方文档中,把 Activity的生命周期理解成为一个金字塔模型,它是基于下面两点:

  • 金字塔的每一个阶梯表示**Activity所处的状态**
  • 回调函数则是各状态转换过程中所通过的路径

这个模型中包含了Activity的六种状态:bash

  • Created:建立完成
  • Started:可见
  • Resumed:可见
  • Paused:部分可见
  • Stopped:不可见
  • Destroyed:销毁

在这六种状态当中,只有ResumedPausedStopped这几种状态在用户没有进一步操做时会保持在该状态,而其他的,都会在执行完相应的回调函数后快速跳过。ide

3、关键生命周期

3.1 protected void onCreate(Bundle savedInstanceState)

  • 该方法被回调时,意味着一个新的Activity被建立了。
  • 因为当前处于一个新的Activity实体对象当中,全部的东西都是未初始化的,咱们通常须要作的事情包括调用setContentView方法设置该Activity的布局,初始化类成员变量。
  • onCreate(xxx)方法执行完以后,Activity就进入了Created状态,然而它并不会在这个状态停留,系统会接着回调onStart() 方法由Created状态进入到Started状态。
  • 注意到,onCreate(xxxx)是全部这些回调方法中惟一有参的,该参数保存了上次因为Activity被动回收时所保存的数据。

3.2 protected void onStart()

  • onStart()方法执行完后,Activity就进入了Started状态,它也一样不会在该状态停留,而是接着回调 onResume()方法进入Resumed状态。
  • onStart()被回调的状况有两种:
  • Created状态过来
  • Stopped状态过来,从这种状态过来还会先通过onRestart()方法。
  • 因为它也会从Stopped状态跳转过来,所以若是咱们在onStop()当中反注册了一些广播,或者释放了一些资源,那么在这里须要从新注册或者初始化,能够认为,onStart()onStop()是成对的关系。
  • CreatedStarted都不是持久性的状态,那么为何要提供一个onStart()回调给开发者呢,直接由Created状态或者是 Stopped状态通过onResume()这条路走到Resumed状态不就能够吗,那么咱们就要分析一下从 onCreate()onStart(),再到onResume()的过程当中,作了哪些其它的操做,这有利于咱们在平时的开发中区分这两个回调的使用场景,咱们来看一下源码。

首先咱们看一下onStart()方法调用的地方,经过下面这段代码,咱们能够知道ActivityonStart()最初是经过Activity#performStart()方法调用过来的:函数

<!-- Activity.java -->
private Instrumentaion mInstrumentation;

final void performStart() {
    mInstrumentation.callActivityOnStart(this);
}

<!-- Instrumentaion.java -->
public void callActivityOnStart(Activity activity) {
   activity.onStart();
}
复制代码

Activity#performStart()方法是由ActivityThread#performLaunchActivity(调过来的:布局

<!-- ActivityThread.java -->
private final void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    Activity a = performLaunchActivity(r, customIntent); //performCreate, performStart()
    if (a != null) { 
        ....
        handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed); //performResume()
       ....
   }
}
//首先看一下调用performCreate, performStart的地方。
private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    mInstrumentation.callActivityOnCreate(activity, r.state); //performCreate
    ....
    if (!r.activity.mFinished) { 
        activity.performStart(); 
        r.stopped = false; 
    }
    if (!r.activity.mFinished) { 
       if (r.state != null) {         
           mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);  //1.onRestoreIntanceState()
       } 
    } 
    if (!r.activity.mFinished) { 
        activity.mCalled = false; 
        mInstrumentation.callActivityOnPostCreate(activity, r.state); //2.onPostCreate
        if (!activity.mCalled) { 
            throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onPostCreate()"); 
       } 
    }
    ...    
}
//这是performResume的入口。
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume) {        
    ActivityClientRecord r = performResumeActivity(token, clearHide);
}
//最后看一下performResume真正执行的地方。
public final ActivityClientRecord performResumeActivity(IBinder token, boolean clearHide) {
    try { 
        if (r.pendingIntents != null) { 
            deliverNewIntents(r, r.pendingIntents); //3.onNewIntent()
            r.pendingIntents = null; 
        } 
       if (r.pendingResults != null) { 
            deliverResults(r, r.pendingResults); //4.onActivityResult()
            r.pendingResults = null; 
      } 
      r.activity.performResume(); 
}
复制代码
  • 经过上面这段代码,咱们能够得出如下几点启发:
  • onStart()onResume()的过程当中,还可能会回调onRestoreInstanceState/onPostCreate/onNewIntent/onActvitiyResult这几个方法。
  • 若是应用退到后台,再次被启动(onNewIntent),或者经过startActivityForResult方法启动另外一个 Activity获得结果返回(onActivityResult)的时候,在onStart()方法当中获得的并非这两个回调的最新结果,由于上面的这两个方法并无调用,而在onResume()当中,这点是能够获得保证的。

3.3 protected void onResume()

  • 该方法被回调时,意味着Activity已经彻底可见了,但这个彻底可见的概念并不等同于Activity所属的WindowAttach了,由于在Activity初次启动的时候,Attach的操做是在回调onResume()以后的,也就是下面的这段代码
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward, boolean reallyResume) {
    ....
    ActivityClientRecord r = performResumeActivity(token, clearHide);
    ....
    if (r.window == null && !a.mFinished && willBeVisible) {
        r.window = r.activity.getWindow();
        View decor = r.window.getDecorView();
        WindowManager.LayoutParams l = r.window.getAttributes();
        ...
        wm.addView(decor, l);
    }
}
复制代码
  • onResume()方法被回调时,因为DecorView并不必定Attach了,所以这时候咱们获取布局内某些View 的宽高获得的值有多是不正确的,既然onResume()当中不能保证,那么onStart()方法也是同理,全部须要在attachToWindow以后才能执行或是指望获得正确结果的操做都须要注意这一点。
  • onResume当中,咱们通常会作这么一些事:在可见时从新拉取一些须要及时刷新的数据、注册 ContentProvider的监听,最重要的是在onPause()中的一些释放操做要在这里面恢复回来。

3.4 protected void onPause()

  • 该方法被回调时,意味着Activity部分不可见,例如一个半透明的界面覆盖在了上面,这时候只要Activity仍然有一部分可见,那么它会一直保持在Paused状态。
  • 若是用户从Paused状态回到Resumed状态,只会回调onResume方法。
  • onPause()方法中,应该暂停正在进行的页面操做,例如正在播放的视频,或者释放相机这些多媒体资源。
  • onPause()当中,能够保存一些必要数据到持久化的存储,例如正在编写的信息草稿。
  • 不该该在这里执行耗时的操做,由于新界面启动的时候会先回调当前页面的onPause()方法,因此若是进行了耗时的操做,那么会影响到新界面的启动时间,官方文档的建议是这些操做应该放到 onStop()当中去作,其实在onStop()中也不该当作耗时的操做,由于它也是在主线程当中的,而在主线程中永远不该该进行耗时的操做。
  • 释放系统资源,例如先前注册的广播、使用的传感器(如GPS)、以及一些仅当页面得到焦点时才须要的资源。
  • 当处于Paused状态时,Activity的实例是被保存在内存中的,所以在其从新回到Resumed状态的过程当中,不须要从新初始化任何的组件。

3.5 protected void onStop()

  • 该方法被回调时,代表Activity已经彻底不可见了。
  • 在任何场景下,系统都会先回调onPause(),以后再回调onStop()
  • 官方文档有谈到,当onStop()执行完以后,系统有可能会销毁这个Activity实例,在某些极端状况下,有可能不会回调onDestroy()方法,所以,咱们须要在onStop()当中释放掉一些资源来避免内存泄漏,而 onDestory()中须要释放的是和Activity相关的资源,如线程之类的(这点平时在工做中不多用,通常咱们都是在onDestroy()中释放全部资源,并且也没有去实现onStart() 方法,究竟何时不会走onDestroy(),这点值得研究,目前的猜想是该Activity在别的地方被引用了,致使其不能回收)。
  • ActivityStopped状态回到前台时,会先回调onRestart()方法,然而咱们更多的是使用onStart() 方法做为onStop()的对应关系,由于不管是从Stopped状态,仍是从Created状态跳转到Resumed状态,都是须要初始化必要的资源的,而它们通过的共同路径是onStart()

3.6 protected void onDestroy()

  • 该方法被回调时,代表Activity是真正要被销毁了,
  • 此时应当释放掉全部用到的资源,避免内存泄漏。
相关文章
相关标签/搜索