Activity 生命周期详解与异常情况生命周期

博主声明:

转载请在开头附加本文链接及作者信息,并标记为转载。本文由博主 威威喵 原创,请多支持与指教。

本文首发于此   博主威威喵  |  博客主页https://blog.csdn.net/smile_running

    在学习 Android 时候,通常一开始学习的都是它的生命周期,谁让我们第一个创建的就是 MainActivity 类呢。学习 Activity 就要从它的生命周期入手,这是我们了解它最快的一种方式,了解它的生命周期,大概就可以知道它的工作时间。比如,我们创建应该 MainActivity 就要重写它的 onCreate 方法,在 onCreate 中通过 setContentView 设置布局文件才能够真正的感受到 Activity 的存在,如果没有 setContentView 就是灰白灰白的,空空如也。

    这次呢。我们先不去管它 setContentView 干了哪些事情,先来把 Activity 的几种生命周期及情境搞明白。百度偷了一张图过来,自己懒得画了,将就看吧:

     这张图,从上到下罗列了 Activity 的几种生命周期,它的几种生命周期分为四中状态,如下图:

下面是一些概念性的描述,蛮看吧,反正也记不住!

onCreate : 该方法是在Activity被创建时回调,它是生命周期第一个调用的方法,我们在创建Activity时一般都需要重写该方法,然后在该方法中做一些初始化的操作,如通过setContentView设置界面布局的资源,初始化所需要的组件信息等。 


onStart : 此方法被回调时表示Activity正在启动,此时Activity已处于可见状态,只是还没有在前台显示,因此无法与用户进行交互。可以简单理解为Activity已显示而我们无法看见摆了。 


onResume : 当此方法回调时,则说明Activity已在前台可见,可与用户交互了(处于前面所说的Active/Running形态),onResume方法与onStart的相同点是两者都表示Activity可见,只不过onStart回调时Activity还是后台无法与用户交互,而onResume则已显示在前台,可与用户交互。当然从流程图,我们也可以看出当Activity停止后(onPause方法和onStop方法被调用),重新回到前台时也会调用onResume方法,因此我们也可以在onResume方法中初始化一些资源,比如重新初始化在onPause或者onStop方法中释放的资源。 


onPause : 此方法被回调时则表示Activity正在停止(Paused形态),一般情况下onStop方法会紧接着被回调。但通过流程图我们还可以看到一种情况是onPause方法执行后直接执行了onResume方法,这属于比较极端的现象了,这可能是用户操作使当前Activity退居后台后又迅速地再回到到当前的Activity,此时onResume方法就会被回调。当然,在onPause方法中我们可以做一些数据存储或者动画停止或者资源回收的操作,但是不能太耗时,因为这可能会影响到新的Activity的显示——onPause方法执行完成后,新Activity的onResume方法才会被执行。 


onStop : 一般在onPause方法执行完成直接执行,表示Activity即将停止或者完全被覆盖(Stopped形态),此时Activity不可见,仅在后台运行。同样地,在onStop方法可以做一些资源释放的操作(不能太耗时)。 


onRestart :表示Activity正在重新启动,当Activity由不可见变为可见状态时,该方法被回调。这种情况一般是用户打开了一个新的Activity时,当前的Activity就会被暂停(onPause和onStop被执行了),接着又回到当前Activity页面时,onRestart方法就会被回调。 


onDestroy :此时Activity正在被销毁,也是生命周期最后一个执行的方法,一般我们可以在此方法中做一些回收工作和最终的资源释放。 

其实,说白了就对应几种状态(创建和销毁状态、可见与不可见状态、是不是可操作状态),如下图:

     每一种生命周期都两两相对,除了 onRestart 比较特殊,单身狗,被孤立了。反正,这样看是很难记住的,太过于概念化的东西容易忘记,必须手动操作一波,记得更牢固。

    来吧,实际操作一下。书本上的老套路,一个 MainActivity,一个 SecondActivity,也许有人会觉得能比书上详细吗?这我不敢说,但是我看的基本入门书,好多都没讲到,也就是介绍一下生命周期而已,一些情境都没涉及到,如果你看下去,就会知道有哪些区别了。

    首先,我们启动一个 Activity 时,第一个启动的是 Application,毫无疑问,Application 的生命周期是最长的,也就是你点开那个桌面小图标时,它就已经启动了。于此同时,Application 就会寻找它下面一级带有 LAUNCHER 的过滤器,然后启动的就是这个 Activity,参考下面的 manifest 代码:

    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:ignore="AllowBackup,GoogleAppIndexingWarning">
        
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SecondActivity" />
        
    </application>

    这里就解释了,Activity 并不是平白无故的启动,只有在清单文件中注册过的才能启动,当然,一个程序是可以不用任何 Activity 的。

    Application 的启动,通常就只有 onCreate 是它的生命周期,在低内存下还会执行其他的方法。Application onCreate 之后,就轮到 MainActivity 的 onCreate,下面来看这一段截图:

 1、当一个 Activity 启动完成时,它的生命周期如上图所示

 onCreate -> onStart 从不可见 到 可见 -> onResume 从不可交互 到 可交互。

2、点击 helloword 启动了 SecondActivity ,生命周期的变化如下:

     MainActivity 没有执行 finish() 方法, 变成了 onStop 停止状态,意味着不可见,不可交互。启动 SecondActivity 生命周期是一样,不再说了。 

3、当点击 back 时,生命周期变化如下:

    首先,它执行的是 SecondActivity 的 onBackPressed 的方法返回。可以看到,MainActivity 在前面执行到 onStop,当按下 back 时,它执行的是 onRestart -> onStart -> onResume

    而 SecondActivity 执行了 onStop -> onDestroy ,表示由停止状态 被 摧毁了。

4、当在 MainActivity 里面执行了 finish() 方法,将 MainActivity 关闭了,又会怎么样呢?

 可以看到,MainActivity finish 后,不仅执行了 onStop,还执行了 onDestroy,彻底的把 MainActivity 给摧毁了。

5、MainActivity 被摧毁了,这时再按 back 会怎么样呢?

 显然 MainActivity 已经没了,两个 Activity 都被摧毁了,最后也只能回到桌面上了。

6、这个时候,再此点击桌面图片,会再次创建 Application 吗?

 答案是不会的,因为我们的 Application 并没有被杀死,所以这里的 App 的 onCreate 就不会再执行了。

7、那如何保证彻底退出应用程序呢,保证杀死 app 呢?

我们通过 SecondActivity 的 onBackPressed() 方法内加入: System.exit(0) ,表示杀死当前应用,彻底退出程序,看看效果:

 点击 back,再次点击桌面图片,发现 App 的 onCreate 执行了,表明我们刚刚成功的杀死这个进程了。

8、切换任务管理快捷键时,生命周期会有什么变化?

9、按下 home 有什么变化呢?

 原来是这样的,是不是发现了什么规律呢?

如果没有执行 finish,那么 Activity 就不会 onDestroy,而按下 back 时,相当于 finish 了,必定执行 onDestroy

当按下 home 和 任务管理 时,这时 Activity 处于不可见状态,但又没有被 finish,所以它只会到 onStop,然后等待被 onReStart,如果这个期间被结束任务了,那它会执行 onDestroy 吗?

 答案是不会的,看上面一个图,从任务里面杀死了 app,并不会执行 onDestroy。

    WTF,写到最后,才发现我前面漏掉了一个 onPause 生命周期方法。由于图太多了,懒得重新弄了。onPause 是会在 onStop 之前执行的,如果 onStop 执行了,那么必定会执行 onPause,自己试一试吧,多的不说了。Activity 息息相关的也就这几种场景的生命周期,属于正常的生命周期。

    还有就是 System.exit(0) 强行把 app 杀死了,这样的话,就会导致 onPause、onStop 、onDestroy 等生命周期没办法执行,如果要保存 Activity 一些数据的话,这样没法从  onPause、onStop 、onDestroy 中获取数据。

    System.exit(0)也是会有问题的,比如在开启 SecondActivity 时,没有把 MainActivity 给 finish 调,这时它又会启动一个新的 MainActivity ,比如出现这样的情况:

 这中情况发生的概率也很高,如果对 System.exit(0) 不了解的话,就会出现问题。解决的方式就是最好新建一个管理所以 Activity 的工具类,在真正需要退出 app 的地方,把 Activity 全部都 finish 掉,然后再 System.exit(0) 就不会有问题了。

还有一种是 ANR 的情况发生,如果等待能完成到还好,如果完成不了,那么这种情况下也不会执行 onPause、onStop 、onDestroy,比如用户在输入完成后提交发生了 ANR,那么这些刚刚填的信息应该如何保证能够保存呢?

 当然,我们可以通过监听控件的事件来保存,这是一种办法。

发布了101 篇原创文章 · 获赞 766 · 访问量 87万+

猜你喜欢

转载自blog.csdn.net/smile_Running/article/details/94356864