Activity 的生命周期和启动模式

xiaoxiao2021-02-28  5

Activity 的生命周期

了解 Activity 的生命周期可以更好的了解每个页面不同时刻的状态,根据不同的状态我们可以进行相应的操作。比如在 Activity 启动时对数据的初始化,在 Activity 关闭时对不需要的数据进行释放。

正常的生命周期

在正常情况下,Activity 会经历如下生命周期;

onCreate() 表示 Activity 正在创建,这时 Activity 生命周期的第一个方法,可以在这里做一些初始化操作,比如 setContentView 去加载布局资源,以及初始化 Activity 页面显示所需的其他数据。

onRestart() 表示 Activity 正在重新启动,调用时机是:当用户按下 Home 键切换到桌面或者用户打开了一个新的 Activity 接着用户又回到这个 Activity 。

onStart() 表示 Activity 正在被启动,这时候 Activity 已经可见(相对系统是可见)但是还没显示在前台,还无法和用户进行交互。

onResume() 表示 Activity 已经可见了,并且可以和用户交互。

onPause() 表示 Activity 正在定制,正常情况下,紧接着 onStop 就会被调用。此时可以做一些存储数据、停止动画等工作,但是注意不能太耗时,因为这会影响到新 Activity 的显示。

onStop() 表示 Activity 即将停止,可以做一些稍微重量级的回首工作,同样不能太耗时。

onDestroy() 表示 Activity 即将被销毁,这时 Activity 生命周期中的最后一个回调,在这里我么可以做一些回首工作和最终的资源释放。

特殊情况: 当用户打开新的 Activity 或者切换到桌面的时候,如果新的 Activity 采用了透明主题,那么当前 Activity 不会回掉 onStop .

问题1:onStart 和onresume、onPause和 onStop 从描述上看差不多,对我们有什么实质的不同呢?

答:onStart 和 onStop 是从 Activity 的可见这个角度来回调的,onStart 是相对于系统可见但是对于用户还是不可见且不可交互的,onStop 对于用户和系统都是不可见的并且不可和用户交互。而 onResume 和 onPause 是从 Activity是 是否位于前台这个角度来回调的,在 onResume 时 Activity 可见位于前台且可以和用户交互,onPause 时 Activity 位于后台,不可和用户交互。

问题2:假设当前 Activity 为 A ,如果这时用户打开了一个新 Activity B 那么 B 的 onResume 和 A 的 onPause 哪个先执行?

答:查看源码可知,Activity 的启动过程的源码相当复杂,涉及到 Instrumentation、ActivityThread 和 ActivityManagerService( 简称 AMS )从源码中可以看出新的 Activity 启动前,站定的 Activity 需要先 onPause 后,新的 Activity 才能启动。验证方法是写一个 Demo 通过在各个生命周期打印 Log 查看执行顺序。

非正常的生命周期

比如当资源相关的系统配置发生改变以及系统内存不足时, Activity 就可能被杀死。

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

当系统配置发生改变后,Activity 会被销毁,其 onPause、onStop、 onDestroy 均会被调用,同时由于 Activity 是在异常情况下终止的,系统会调用 onSaveInstanceState 来保存当前 Activity 的状态。

onSaveInstanceState 的调用时机是在 onStop 之前,但是不一定在 onPause 之后。

当 Activity 被异常终止且重建后,系统会调用 onRestoreInstanceState, 并把 Activity 销毁时 onSaveInstanceState 保存的 Bundle 数据传递给 onRestoreInstanceState 和 onCreate 方法。

因此可以通过 onRestoreInstanceState 和 onCreate 方法来判断 Activity 是否被重建;而且从时序上来说,onRestoreInstanceState 的调用时机在 onStart 之后。

资源内存不足导致低优先级的 Activity 被杀死

Activity 的优先级情况,从高到低可以分为以下三种:

(1) 前台 Activity :正在和用户交互的 Activity ,优先级最高

(2) 可见但非前台 Activity :比如 Activity中弹出了一个对话框,导致 Activity可见但是位于后台无法和用户直接交互

(3) 后台 Activity :已经被暂停的 Activity,比如执行了 onStop , 优先级最低

Activity 的启动模式

有时候为了满足项目的特殊需求,就必须使用 Activity 的启动模式,所以我们必须要搞清楚它的启动模式和标志位

Activity 为什么需要启动模式?

在默认情况下,当我们多次启动同一个 Activity 的时候,系统会创建多个实例并把它们一一放入任务栈中,当我们按下返回键,这些 Activity 会一一回退。这个任务栈时一种“后进先出”的栈结构,也就是最后进来的 Activity 最先出去。但是当我们多次启动同一个 Activity 系统会重复创建多个实例,Android 在设计idea时候为了解决这个问题,它提供了启动模式来修改系统的默认行为。目前又四种启动模式:standard、singleTop、singleTask、singleInstance.

standard

这时系统的默认模式,每次启动一个 Activity 都会重新创建一个新的实例,不管这个实例是否已经存在。

singleTop

栈顶复用模式。在该模式下,如果新的 Activity 已经位于任务栈的栈顶,那么此 Activity 不会被重新创建,同时它的 onNewIntent 方法会被回掉,通过重写此方法我们可以取出当前请求的信息。

protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent);//must store the new intent unless getIntent() will return the old one } singleTask

栈内复用模式。这是一种单实例模式,在该模式下,只有 ACtivity 在一个栈中存在,那么多次启动此 Activity 都不会重新创建实例,和 singleTop 一样,体统也会回调其 onNewInstent。

singleInstance

单实例模式。这话i是一种加强的 singleTask 模式,它除了具备 singleTask 的所有特性外,还加强了一点,那就是具有此种模式的 Activity 只能单独的位于任务栈中。

如何给 Activity 设置启动模式呢?

有两种方式,(1)是通过 AndroidMenifest 中为 Activity 指定启动模式 (2) 在 Intent 中设置标志位来为 Activity 指定启动模式。两种方式的优先级是(2)优先于(1),当两种方式存在时,以第二种方式为准。当然这两种方式还是有差异的,比如(1)无法啊直接为 Activity 设置 FLAG_ACTIVITY_CLEAR_TOP标志,而 (2) 无法为 Activity 指定 singleInstance 模式。

通过 AndroidMenifest 中为 Activity 指定启动模式 <activity android:name="..activity.MultiportActivity" android:launchMode="singleTask"/><!--指定标志位--> 在 Intent 中设置标志位来为 Activity 指定启动模式 Intent intent = new Intent(); intent.setClass(context, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//指定标志位 context.startActivity(intent);

查看任务栈的命令

adb shell dumpsys activity在导出的信息中重点查看Running activitys

Activity 的 Flags

在 Intent 中设置 Activity 的启动模式时可以通过 Flags 设置,这里的 Flags 不仅仅是可以设置启动模式,还可以影响 Activity 的运行状态。比如设置了 FLAG_ACTIVITY_CLEAR_TOP 的Activity 表示在同一个任务栈中所有位于它上面的 Activity 都要出栈,这个标志位一般会和 singleTask 启动模式一起出现,而且 singleTask 模式是默认具有此标志位的效果。

转载请注明原文地址: https://www.6miu.com/read-2800272.html

最新回复(0)