阅读Android官方教程 Google Training 1.3 ----- Manage the Activity Lifecycle

阅读谷歌官方教程第一章 Getting Started


这次官方的内容竟然是中文的,但是内容涉及到了Activity的生命周期的管理,看完感觉内容很丰满,学到了很多东西啊。看完这节教程,觉得原来自己开发的时候几个周期方法简直是乱用,知道个大概就开始乱套,遇到问题上网百度到了,也就是应付一下,再来一个fragment简直就要爆炸了,这篇文章的篇幅很长,但我觉得都很有用啊。希望借这个机会好好认识一下生命周期。

ps: 这次由于官方教程都是中文,所以可能引用内容会不十分准确,但看起来会轻松一些。内容多,但基本都是很好的东西。


管理Activity生命周期

这是这次内容的大标题, 下面是很长的一段官方对Activity生命周期的介绍。

当用户导航、退出和返回您的应用时,应用中的 Activity 实例将在其生命周期中转换不同状态。 例如,当您的Activity初次开始时,它将出现在系统前台并接收用户焦点。 在这个过程中,Android 系统会对Activity调用一系列生命周期方法,通过这些方法,您可以设置用户界面和其他组件。 如果用户执行开始另一Activity或切换至另一应用的操作,当其进入后台(在其中Activity不再可见,但实例及其状态完整保留),系统会对您的Activity调用另外一系列生命周期方法。

既然学习Google的教程,就要从本质上提问,不再盲目学习了。

我会这么问:管理它有啥用?

Google回答:

在生命周期回调方法内,您可以声明 用户离开和再次进入Activity时的Activity行为。比如,如果您正构建流视频播放器,当用户切换至另一应用时,您可能要暂停视频或终止网络连接。当用户返回时,您可以重新连接网络并允许用户从同一位置继续播放视频。

通过学习每个 Activity 实例接收的重要生命周期回调方法以及您如何使用这些方法以使您的Activity按照用户预期进行并且当您的Activity不需要它们时不会消耗系统资源。

这么一细想也确实是啊,以前自己做的水水的APP,在首页里面随便嵌套一个什么东西,fragment切换就卡的飞起,和Google官方视频的切换动画比起来真是菜的抠脚。恩,那就下来就开始快乐的学习吧。

这次有四个小节的内容:

  • 开始Activity

    • 学习有关Activity生命周期、用户如何启动您的应用以及如何执行基本Activity创建操作的基础知识。
  • 暂停和继续Activity

    • 学习Activity暂停时(部分隐藏)和继续时的情况以及您应在这些状态变化期间执行的操作。
  • 停止和重新开始Activity

    • 学习用户完全离开您的Activity并返回到该Activity时发生的情况。
  • 重新创建Activity

    • 学习您的Activity被销毁时的情况以及您如何能够根据需要重新构建Activity。

第一个内容:开始Activity

因为官方内容实在是太精炼了,我直接引用了:

1.了解生命周期回调

在Activity的生命周期中,系统会按类似于阶梯金字塔的顺序调用一组核心的生命周期方法。 也就是说,Activity生命周期的每个阶段就是金字塔上的一阶。 当系统创建新Activity实例时,每个回调方法会将Activity状态向顶端移动一阶。 金字塔的顶端是Activity在前台运行并且用户可以与其交互的时间点。

当用户开始离开Activity时,系统会调用其他方法在金字塔中将Activity状态下移,从而销毁Activity。 在有些情况下,Activity将只在金字塔中部分下移并等待(比如,当用户切换到其他应用时),Activity可从该点开始移回顶端(如果用户返回到该Activity),并在用户停止的位置继续。
这里写图片描述

这张图很清晰地展示了Activity启动到销毁的生命周期,以及各个状态之间切换时调用的方法。但只有在顶端时,我们是可以看到Activity并且和Activity获得焦点,然后我们可以和它进行交互的。

根据Activity的复杂程度,可能不需要实现所有生命周期方法。 但是,了解每个方法并实现确保APP按照用户期望的方式运行的方法非常重要。 正确实现Activity生命周期方法可确保APP按照以下几种方式良好运行:

  • 如果用户在使用APP时接听来电或切换到另一个应用,它不会崩溃。
  • 在用户未主动使用它时不会消耗宝贵的系统资源。
  • 如果用户离开APP并稍后返回,不会丢失用户的进度。
  • 当屏幕在横向和纵向之间旋转时,不会崩溃或丢失用户的进度。

确实很重要,如果一切换就卡得飞起,我肯定会把这个垃圾APP卸载掉。接着看着:

Activity看起来有这么多的状态,其实只有三个状态是真正静止的:

1. 继续

  • — 换句话说就是金字塔顶端的状态,用户在这个点进行交互。

2. 暂停

  • Paused状态,Activity被在前台中处于半透明状态或者未覆盖整个屏幕的另一个Activity— 部分阻挡。 暂停的Activity不会接收用户输入并且无法执行任何代码。

3. 停止

  • Stopped状态下,Activity被完全隐藏并且对用户不可见;它被视为处于后台。 停止时,Activity实例及其诸如成员变量等所有状态信息将保留,但它无法执行任何代码。

其他状态(“创建”和“开始”)是瞬态,系统会通过调用下一个生命周期回调方法从这些状态快速移到下一个状态。 也就是说,在系统调用 onCreate() 之后,它会快速调用 onStart(),紧接着快速调用 onResume()。

到这里我也才知道了原来 Paused 状态和 Stopped 状态的区别是主要可见性的差别。


2.指定您的应用的启动器Activity

这个内容比较简单,就是点击应用图标的时候第一个启动的Activity,这个启动器可以在 AndroidManifest.xml 里面指定,如下:

<activity android:name=".MainActivity" android:label="@string/app_name">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

不过也有个小的知识点:如果未对Activity之一声明 MAIN 操作或 LAUNCHER 类别,那么您的应用图标将不会出现在应用的主屏幕列表中。

真是有趣,不过我还没试过。


3.创建一个新实例

不管你是点击图标创建Activity还是在交互时创建,Android在Activity启动时都会调用 onCreate() 方法创建Activity的实例,在里面可以声明用户界面(在 XML 布局文件中定义)、定义成员变量,以及配置某些 UI。这个大家都知道,不过连这个看了一下官方代码都还有可以学习的地方,代码如下:

TextView mTextView; // Member variable for text view in the layout

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Set the user interface layout for this Activity
    // The layout file is defined in the project res/layout/main_activity.xml file
    setContentView(R.layout.main_activity);

    // Initialize member TextView so we can manipulate it later
    mTextView = (TextView) findViewById(R.id.text_message);

    // Make sure we're running on Honeycomb or higher to use ActionBar APIs
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // For the main activity, make sure the app icon in the action bar
        // does not behave as a button
        ActionBar actionBar = getActionBar();
        actionBar.setHomeButtonEnabled(false);
    }
}

他比我多了一个确定系统运行版本的判断语句,这部分在上一节 Supporting Different Platform 的时候提到了,通过这个代码可以确定,需要更高级别API的代码可以如我们预期一样正常运行,如果设备API版本过低不会产生我们不想要的效果。

一旦 onCreate() 完成执行操作,系统会相继调用 onStart() 和 onResume() 方法。 您的Activity从不会驻留在“已创建”或“已开始”状态。在技术上,Activity会在 onStart() 被调用时变得可见,但紧接着是 onResume(),且Activity保持“继续”状态,直到有事情发生使其发生变化,比如当接听来电时,用户导航至另一个Activity,或设备屏幕关闭。启动部分的运行图如下所示:
这里写图片描述


4.销毁Activity

当Activity的第一个生命周期回调是 onCreate() 时,它最近的回调是 onDestroy()。系统会对您的Activity调用此方法,作为您的Activity实例完全从系统内存删除的最终信号。

大多数应用不需要实现此方法,因为本地类引用与Activity一同销毁,并且您的Activity应在 onPause() 和 onStop() 期间执行大多数清理操作。 但是,如果您的Activity包含您在 onCreate() 期间创建的后台线程或其他如若未正确关闭可能导致内存泄露的长期运行资源,您应在 onDestroy() 期间终止它们。

@Override
public void onDestroy() {
    super.onDestroy();  // Always call the superclass

    // Stop method tracing that the activity started during onCreate()
    android.os.Debug.stopMethodTracing();
}

注意:在所有情况下,系统在调用 onPause() 和 onStop() 之后都会调用 onDestroy() ,只有一个例外:当您从 onCreate() 方法内调用 finish() 时。在有些情况下,比如当您的Activity作为临时决策工具运行以启动另一个Activity时,您可从 onCreate() 内调用 finish() 来销毁Activity。 在这种情况下,系统会立刻调用 onDestroy(),而不调用任何其他 生命周期方法。

一般来说,资源的释放大多数我们应该留在 onPause() 和 onStop() 这两个方法完成,onDestroy() 是用来关闭最后一点还没有被我们释放的资源。看得出来,一个优秀APP不会卡顿就是因为攻城狮对这几个方法的恰当使用,膜拜, 方法代码感觉更接近底层,我根本没有接触过。


第二个内容:暂停和继续Activity

什么是暂停,什么是停止,上面提到了,这节教程又说明了:

在正常使用应用的过程中,前台Activity有时会被其他导致Activity暂停的可视组件阻挡。 例如,当半透明Activity打开时(比如对话框样式中的Activity),上一个Activity会暂停。只要Activity仍然部分可见但目前又未处于焦点之中,它会一直暂停。

但是,一旦Activity完全被阻挡并且不可见,它便停止。

很好的说明。

我们应该在暂停时做什么呢?做的东西很多啊,通过该方法,您可以停止不应在暂停时继续的进行之中的操作(比如视频)或保留任何应该永久保存的信息,以防用户坚持离开应用。

什么叫坚持离开用户,个人认为这是APP用户行为的,就是说用户离开Activity,让它出于暂停状态(部分可见),然后焦点回来时,通常代表用户马上要离开这个APP了,这个时候,我们应该把之前应该保存的信息保留下来,别人要马上要走了,回来一看,又要重新输入一遍,或是,哎我的视频怎么没停啊,智障APP,所以我们应该在这个状态保存一些信息,或是停止一些操作。

这个状态的流程图,是下面这样的:
这里写图片描述
当半透明Activity阻挡您的Activity时,系统会调用 onPause() 并且Activity会在“暂停”状态下等待 (1)。 如果用户在Activity仍然处于暂停状态时返回Activity,则系统会调用 onResume() (2)。

下面我们对在这两个方法里面具体要做什么说明一下:


1. 暂停Activity

就是在金字塔顶端的时候调用了一下onPause()方法,一般Activity进入这个状态以后,意味着离Activity进入停止状态也不远了,我们应该在这个状态里面释放一些资源,让我们的APP运行流转更加顺畅。

  • 停止动画或其他可能消耗 CPU 的进行之中的操作。
  • 提交未保存的更改,但仅当用户离开时希望永久性保存此类更改(比如电子邮件草稿)。
  • 释放系统资源,比如广播接收器、传感器手柄(比如 GPS) 或当您的Activity暂停且用户不需要它们时仍然可能影响电池寿命的任何其他资源。

我看了真实惊了,人家连电池寿命都考虑到了,一想我也真是个蛮子,自己开心就好。不过确实动画还好,不太常见,以后遇到会注意,但是保存更改,比如草稿之类的,这个操作应该要记住以后再onPause()里面完成,释放资源也很重要,万一你用了其他的APP正好要用却用不上,用户肯定或说一开这个微信就用不了,这个垃圾软件。。。。看一个例子释放相机资源吧:

@Override
public void onPause() {
    super.onPause();  // Always call the superclass method first

    // Release the Camera because we don't need it when paused
    // and other activities might need to use it.
    if (mCamera != null) {
        mCamera.release()
        mCamera = null;
    }
}

除了我们应该做什么,还有几个不应该做的:

  1. 使用 onPause() 永久性存储用户更改(比如输入表格的个人信息)。 只有在您确定用户希望自动保存这些更改的情况(比如,电子邮件草稿)下,才能在 onPause()中永久性存储用户更改。
    这个很好理解吧,一般除了草稿,大家都不想随便填的东西每天确定你就给保存了,那也太坑了,注意用户体验。

  2. 避免在 onPause() 期间执行 CPU 密集型工作,比如向数据库写入信息,因为这会拖慢向下一Activity过渡的过程(您应改为在 onStop()期间执行高负载关机操作。
    这个也很重要,毕竟要保证切换顺畅,释放资源一下就好,别弄得卡顿了。


2. 继续Activity

这个是在暂停状态重新获得焦点,调用onResume()方法。我们在这个方法里要干嘛,当然是要重新初始化我们在onPause()里面释放掉的一些资源,还有初始化动画,那些应该在获得焦点时应该出现东西。

官方举了一个重新初始化被释放的相机的例子:

@Override
public void onResume() {
    super.onResume();  // Always call the superclass method first

    // Get the Camera instance as the activity achieves full user focus
    if (mCamera == null) {
        initializeCamera(); // Local method to handle camera init
    }
}

第三个内容:停止并重新开始Activity

暂停状态是部分可见,那么停止状态就是不可见了,我们直接看官方解释:

正确停止和重新开始Activity是Activity生命周期中的重要过程,其可确保您的用户知晓应用始终保持Activity状态并且不会丢失进度。有几种Activity停止和重新开始的关键场景:

  • 用户打开“最近应用”窗口并从您的应用切换到另一个应用。当前位于前台的您的应用中的Activity将停止。 如果用户从主屏幕启动器图标或“最近应用”窗口返回到您的应用,Activity会重新开始。
  • 用户在您的应用中执行开始新Activity的操作。当第二个Activity创建好后,当前Activity便停止。 如果用户之后按了返回按钮,第一个Activity会重新开始。
  • 用户在其手机上使用您的应用的同时接听来电。

Activity 课程提供两种生命周期方法:onStop() 和 onRestart(),这些方法允许您专门处理正在停止和重新开始的Activity。 不同于识别部分 UI 阻挡的暂停状态,停止状态保证 UI 不再可见,且用户的焦点在另外的Activity(或完全独立的应用)中。

注意:因为系统在停止时会将您的 Activity 实例保留在系统内存中,您根本无需实现 onStop() 和 onRestart()或甚至onStart() 方法。对于大多数相对简单的Activity而言, Activity将停止并重新开始,并且您可能只需使用 onPause() 暂停正在进行的操作,并从系统资源断开连接。

这一部分的运行图如下所示:
这里写图片描述
用户离开Activity时,系统会调用 onStop() 停止Activity(1)。 如果用户在Activity停止时返回,系统会调用 onRestart() (2),紧接着调用 onStart() (3) 和 onResume() (4)。 注意:无论什么场景导致Activity停止,系统始终会在调用 onStop() 之前调用 onPause()。

下面我们分别看看在停止和重新开始Activity的时候我们应该做什么:


1. 停止Activity

当Activity进入停止状态的时候,我们应该释放到我们应该释放掉的所有资源,为什么这么说呢,我们知道当手机内存不足的时候,系统会可能会销毁Activity的实例,但这个时候不会调用onDestroy()方法。所以为了保证我们的Activity不被杀死,及时的释放资源真的很重要。

尽管 onPause() 方法在 onStop()之前调用,您应使用 onStop() 执行更大、占用更多 CPU 的关闭操作,比如向数据库写入信息。因为在onPause()方法里面调用密集型的CPU操作可能会导致Activity之间的切换不连续,造成不好的用户体验。

官方给出了一个在onStop()方法里面保存草稿的例子:

@Override
protected void onStop() {
    super.onStop();  // Always call the superclass method first

    // Save the note's current draft, because the activity is stopping
    // and we want to be sure the current note progress isn't lost.
    ContentValues values = new ContentValues();
    values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
    values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());

    getContentResolver().update(
            mUri,    // The URI for the note to update.
            values,  // The map of column names and new values to apply to them.
            null,    // No SELECT criteria are used.
            null     // No WHERE columns are used.
            );
}

看一段官方的说明对于停止状态view状态的说明:

当您的Activity停止时, Activity 对象将驻留在内存中并在Activity继续时被再次调用。 您无需重新初始化在任何导致进入“继续”状态的回调方法过程中创建的组件。 系统还会在布局中跟踪每个 View 的当前状态,如果用户在 EditText 小工具中输入文本,该内容会保留,因此您无需保存即可恢复它。

注意:即使系统在Activity停止时销毁了Activity,它仍会保留 Bundle(键值对的二进制大对象)中的 View 对象(比如 EditText 中的文本),并在用户导航回Activity的相同实例时恢复它们

其实第一段话我们都知道,就是比如说你在记事本打字,先切换了一个Activity,然后又切换回来,光标还在原来的地方闪烁,第二段话有点东西在里面,就是比如说你的Activity在暂停的时候太耗内存了,系统销毁了实例,但是你在最近应用的窗口里还是可以看到,但是点击它,它会重新创建实例(因为原来的实例已经被销毁了),但是重新启动之后,你的原来的操作痕迹可能还在,比如看输入框里面的文本。

2. 开始/重新开始Activity

当您的Activity从停止状态返回前台时,它会接收对 onRestart() 的调用。系统还会在每次您的Activity变为可见时调用 onStart() 方法(无论是正重新开始还是初次创建)。 但是,只会在Activity从停止状态继续时调用 onRestart() 方法,因此您可以使用它执行只有在Activity之前停止但未销毁的情况下可能必须执行的特殊恢复工作。

应用需要使用 onRestart() 恢复Activity状态的情况并不常见,因此没有适用于一般应用群体的任何方法指导原则。 但是,因为您的 onStop() 方法应基本清理所有Activity的资源,您将需要在Activity重新开始时重新实例化它们。 但是,您还需要在您的Activity初次创建时重新实例化它们(没有Activity的现有实例)。 出于此原因,您应经常使用 onStart() 回调方法作为 onStop() 方法的对应部分,因为系统会在它创建您的Activity以及从停止状态重新开始Activity时调用 onStart() 。

上面两段话一共提到两点内容,一个是onRestart()方法进行重新开始后的特殊恢复工作(一般用不着),另一个是onStart()方法来恢复onStop()方法释放掉的资源。

官方举了一个在onStart()方法里面开启GPS资源的示例:

@Override
protected void onStart() {
    super.onStart();  // Always call the superclass method first

    // The activity is either being restarted or started for the first time
    // so this is where we should make sure that GPS is enabled
    LocationManager locationManager =
            (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

    if (!gpsEnabled) {
        // Create a dialog here that requests the user to enable GPS, and use an intent
        // with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action
        // to take the user to the Settings screen to enable GPS when they click "OK"
    }
}

@Override
protected void onRestart() {
    super.onRestart();  // Always call the superclass method first

    // Activity being restarted from stopped state
}

当系统销毁您的Activity时,它会调用您的 Activity 的 onDestroy() 方法。因为您通常应已使用 onStop() 释放大多数您的资源,到您接收对 onDestroy() 的调用时,大多数应用无需做太多操作。 此方法是您清理可导致内存泄露的资源的最后一种方法,因此您应确保其他线程被销毁且其他长期运行的操作(比如方法跟踪)也会停止。


第四个内容:重新创建Activity

先来看一段官方对销毁Activity情况的描述:

在有些情况下,您的Activity会因正常应用行为而销毁,比如当用户按 返回按钮或您的Activity通过调用 finish()示意自己的销毁。 如果Activity当前被停止或长期未使用,或者前台Activity需要更多资源以致系统必须关闭后台进程恢复内存,系统也可能会销毁Activity。

当您的Activity因用户按了返回 或Activity自行完成而被销毁时,系统的 Activity 实例概念将永久消失,因为行为指示不再需要Activity。 但是,如果系统因系统局限性(而非正常应用行为)而销毁Activity,尽管 Activity 实际实例已不在,系统会记住其存在,这样,如果用户导航回实例,系统会使用描述Activity被销毁时状态的一组已保存数据创建Activity的新实例。 系统用于恢复先前状态的已保存数据被称为“实例状态”,并且是 Bundle 对象中存储的键值对集合。

概括来讲,一般销毁分两种:

  • 正常(用户按下返回键或调用finish())
  • 非正常(系统内存调用不足对后台应用非正常销毁)

但值得注意的是,旋转屏幕也是一种销毁,因为你的Activity可能会在横向或是纵向的时候加载不同的布局文件,会销毁并重新创建前台实例。

默认情况下,系统会使用 Bundle 实例状态保存您的Activity布局(比如,输入到 EditText 对象中的文本值)中有关每个 View 对象的信息。 这样,如果您的Activity实例被销毁并重新创建,布局状态便恢复为其先前的状态,且您无需代码。 但是,您的Activity可能具有您要恢复的更多状态信息,比如跟踪用户在Activity中进度的成员变量。没错,这就应该是onCreate()里面那个Bundle bundle参数的作用。。吧 。。。。。。

如果要保存实例的状态别忘了这一点:为了 Android 系统恢复Activity中视图的状态,每个视图必须具有 android:id 属性提供的唯一 ID。

要保存有关Activity状态的其他数据,您必须替代 onSaveInstanceState() 回调方法。当用户要离开Activity并在Activity意外销毁时向其传递将保存的 Bundle 对象时,系统会调用此方法。 如果系统必须稍后重新创建Activity实例,它会将相同的 Bundle 对象同时传递给 onRestoreInstanceState() 和 onCreate() 方法。

下面是Android销毁实例保存状态并重新创建恢复状态的图解:
这里写图片描述
当系统开始停止您的Activity时,它会 调用 onSaveInstanceState() (1),因此,您可以指定您希望在 Activity 实例必须重新创建时保存的额外状态数据。如果Activity被销毁且必须重新创建相同的实例,系统将在 (1) 中定义的状态数据同时传递给 onCreate() 方法(2) 和 onRestoreInstanceState() 方法(3)。

下面我们具体看看保存状态和恢复状态这两种情况。


1. 保存Activity状态

先看官方对保存onSaveInstanceState()状态方法的表述:

当您的Activity开始停止时,系统会调用 onSaveInstanceState() 以便您的Activity可以保存带有键值对集合的状态信息。 此方法的默认实现保存有关Activity视图层次的状态信息,例如 EditText 小工具中的文本或ListView 的滚动位置。

要保存Activity的更多状态信息,您必须实现 onSaveInstanceState() 并将键值对添加至 Bundle 对象

在之前我们也提到,系统会自动帮我们保存一些状态比如上次打字打到哪里之类的比较简单的状态信息,但是如果APP设计者考虑得更加人性化一点,肯定会需要有更多的Acticiy状态需要我们进行保存,那就要靠这个onSaveInstanceState()方法了。比如上次我们看新闻看到哪里了,不然想继续看的时候打开又要重头开始发翻。

看一下官方给出了一个示例:

static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
    // Save the user's current game state
    savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
    savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

最后调用了这个方法的超类的一个方法,目的是保存视图层次的状态(在View中Android定义了saveHierarchyState,它用来保存这个View所在的视图树的状态,传进来的参数是父view保存的状态),官方代码都比较深入。


2. 恢复Activity状态

看一段官方的叙述先:

当您的Activity在先前销毁之后重新创建时,您可以从系统向Activity传递的 Bundle 恢复已保存的状态。onCreate() 和 onRestoreInstanceState() 回调方法均接收包含实例状态信息的相同 Bundle。

因为无论系统正在创建Activity的新实例还是重新创建先前的实例,都会调用 onCreate() 方法,因此您必须在尝试读取它之前检查状态 Bundle 是否为 null。 如果为 null,则系统将创建Activity的新实例,而不是恢复已销毁的先前实例。

就是说重新创建的时候,如果我们之前用onSaveInstanceState()方法保存了一些Activity信息,再次启动该Activity时,系统自动会将保存了信息的Bundle传递给onCreate() 和 onRestoreInstanceState() 回调方法,来恢复,无论系统正在创建Activity的新实例还是重新创建先前的实例,都会调用 onCreate() 方法,所以重点来了:我们应该在尝试读取它之前检查状态 Bundle 是否为 null。 如果为 null,则系统将创建Activity的新实例,而不是恢复已销毁的先前实例。

看一下官方的示例:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState); // Always call the superclass first

    // Check whether we're recreating a previously destroyed instance
    if (savedInstanceState != null) {
        // Restore value of members from saved state
        mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
        mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
    } else {
        // Probably initialize members with default values for a new instance
    }
    ...
}

除此之外,还有第二种方式

您可以选择实现系统在 onStart() 方法之后调用的 onRestoreInstanceState() ,而不是在onCreate() 期间恢复状态。 系统只在存在要恢复的已保存状态时调用 onRestoreInstanceState() ,因此您无需检查 Bundle 是否为 null:

public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from saved instance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
    mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
}

现在终于能懂一些之前在网上搜的一部分看不懂的代码了,呵呵哒。


好了,关于Activity的内容就这么多了,多是细节,要一直放在心里才能不忘记,以后实践的时候会带上亲爱的几个生命周期的回调方法的,希望告别卡顿。今天就到这里吧,写了好多啊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值