Activity 的 36 大难点,你会几个?「建议收藏」
前言
- 学习Android已有段时间了。一直以来都专注于学习新知识。最近发现许多常用但重要的知识点竟然忘记掉了。趁这几天的时间打算把关于Activity的内容梳理出来并整理成问题形式,并分享出来帮助大家查缺补漏。
在本文里,我决定彻底摒弃过去写博客的方法,并整篇文章采用 XMind 技术整合所有知识点为思维导图形式展示。欢迎参考或学习这篇内容。
文章目录

方便大家学习,我在 GitHub 上建立个 仓库
仓库内容将保持同步更新状态。我的个人账号在稀土掘金、简书、及博客园等多个平台随时都能获取最新资讯。建议大家及时关注该官方仓库账号以获取重要内容
仓库地址:
深度总结 Android 、JVM 、算法等知识点!感谢您的支持与鼓励!期待您的Star和评论!
神图
- 在深入了解Android开发的过程中, 先让我们探索一下具体包括哪些功能的东西?
- 借助一张专业级的解析图, 我们将深入学习Activity的基本概念。

一、 生命周期
- 我们生命周期先看看具体有哪些方法回调,在逐一攻破:
1.1 Dialog 弹出时

- 此为创建对话框时的情况
- 当跳转至非全屏的
Activity时,则会按照正常流程处理 - 即通过将 onPasue() 更名为 onPause() 来实现这一功能(确保前一页面仍能正常显示)
1.2 横竖屏切换时

在未配置 android:configChanges 情况下,默认情况下,在切屏操作时系统将依次重新激活各个生命周期组件,在横向切屏操作中将被调用一次,在纵向切屏操作中则会被调用两次
在配置设置中将 Activity 的 android:configChanges 属性设为 'orientation' 时,在执行截屏操作会触发所有周期性的初始化流程;而横向或纵向截屏操作仅进行一次。
当设置 Android Activity 的属性 android:configChanges 设置为 "orientation|keyboardHidden" 时,切屏操作不会在所有生命周期之间切换,并且只会触发唯一的一个配置更改事件处理方法。
注意:还有一点特别重要的是一个与 Android 相关的变更细节!当 API 版本大于 12 的时候,必须在代码中添加 screenSize 属性;否则在屏幕切换过程中即使你设置 orientation 属性也会导致 Activity 被重新创建。
不论横竖屏切换操作如何进行,其生命周期的执行过程仍需确保稳定可靠
1.3 不同场景下 Activity 生命周期的变化过程

image
- 启动流程:依次触发
onCreate()、.onStart()和onResume()事件后完成,并使Activity进入运行状态。- 在锁屏状态下会调用
onPause()和stopping()事件;而开屏时应调用start()和resume()事件。
- 在锁屏状态下会调用

- 当 Activity 转移到新的界面或通过 Home 键返回主屏时: onPause() → onStop() ,进入停滞状态。
- 当 Activity 返回前台时: onRestart() → onStart() → onResume() ,重新进入运行状态。
- 此外,在内存不足的情况下:系统将终止该后台的 Activity;若再次尝试唤醒该 Application,则需经历 onCreate() → onStart() → onResume().
1.4 将一个 Activity 设置成窗口的样式

在配置时仅需为我们的该 Android 活动设置以下属性参数就足够了。
`
android:theme="@android:style/Theme.Dialog"
1.5 退出已调用多个 Activity 的 Application
一般情况下,开发者退出一个 Activity 时只需按下回车键即可。要实现退出 activity ,只需调用其 finish() 函数即可。

- 发送特定广播:
当应用需要结束时,在满足某些条件的情况下发送一个唯一指定的广播;每个Activity接收到该广播后即可完成关闭操作。
为此目的设计了一种机制,在满足特定条件下自动完成相关操作。
为了实现这一功能,在启动该机制之前必须先调用函数 registerReceiver(receiver, filter)。
- 递归退出
通过调用该方法来终止当前的Activity。
当启动一个新的Activity时,请使用startActivityForResult函数启动该Activity,并在其返回值处设置标记。
在on
- 其实
- 其中一种方式是通过
intent的相关属性来配置并激活一个新的activity。
2. 当系统检测到当前任务栈中已经存在该特定的 Activity 时,它会清除所有相关的 Activity。
3. 这实际上等同于将 Activity 设置为单线程模式。
- 记录打开的
Activity
- 每打开一个
Activity, 就记录下来。 - 在需要退出时 , 关闭每一个
Activity
1.6 锁定屏与解锁屏幕,Activity 如何执行生命周期

- 锁屏时会执行
onPause()和onStop(), 而开屏时则应该执行onStart()onResume()
1.7 修改 Activity 进入和退出动画

- 主要途径有两类 , 其中一类是通过定义活动的主题来实现 ,另一类则是通过覆盖活动的 overridePendingTransition 方法来完成。
- 在风格配置文件中进行样式设置的方法有两种:一种是将主题样式存储于 styles.xml 文件中以辅助编辑代码 ,另一种则是创建 themes.xml 文件并将该文件整合到 AndroidManifest.xml 中为特定活动指定主题样式。
- 实现 overridePendingTransition 方法的具体操作可以通过如下代码片段得以体现:overridePendingTransition(R.anim.fade, R.anim.hold)。
1.8 Activity 的四种状态

running:users may interact with an activity that is located at the stack's top position.- When an activity loses focus, it may be overlapped by another activity or covered by a semi-transparent overlay activity. The overlapped activity remains in a paused state without being destroyed, retaining all its state information and member variables but cannot be interacted with. (In cases of memory constraints, this paused activity might be garbage-collected by the system.)

covered:这个activity被另外一个activity完全覆盖的同时,并且即便如此它仍然保留了所有的状态信息以及成员变量(除了内存紧张)destroyed:该activity被销毁之后其所有的状态信息以及成员变量都已经不再存在
1.9 如何处理异常退出

- 当某个Activity发生异常退出时 → onPause() → onSaveInstanceState() → onStop() → onDestory()
- 需要注意的是,在 onSaveInstanceState() 方法与 onPause 的调用顺序并非严格固定,在某些情况下其调用顺序并非严格固定,在某些情况下在其执行后仍有可能调用(即在其执行后仍有可能调用),但无论如何都会在其执行前完成stop操作
- 当某个Activity发生异常退出后再次启动时 → onCreate() → onStart() → onRestoreInstanceState() → onResume()

- 首先理解这个生命周期的关键步骤后就能够解决这个问题了。首先要明确面试官的需求:是要重新启动并恢复当前这个 Activity ,还是直接退出整个 app ?
- 如果需要恢复该 Application 的状态,则应在
$onSaveInstanceState()方法中保存相关信息,并在后续的$onRestoreInstanceState()方法中完成数据复原。 - 如果选择退出该 Application,则应在发生异常时捕获全局错误信息,并采取相应措施以确保 Application 安全退出。
- 个人认为建议在 Application 启动时启用全局异常被捕获机制,并采取有效措施以确保 Application 安全退出。这不仅可以减少因崩溃导致的问题影响(如内存泄漏等),还能提升整体应用稳定性。
1.10 什么是 onNewIntent

当 IntentActivity 位于任务栈顶端时,这表示曾打开过的 Activity 现已处至此状态。若有其他应用随后发送 Intent 则会触发此逻辑。
执行顺序为:onNewIntent,onRestart,onStart,onResume。
二、 启动模式
2.1 启动模式

Activity包含以下四个不同的launchMode:standard, singleTop, singleTask, singleInstance.

Standard模式(默认模式)
每当启动一个Activity时, 都会又一次创建一个新的实例入栈, 无论该实例是否已经存在.
生命周期:每个新生成的 Activity 遵循常规流程,在此期间它的 onCreate 、onStart 和 onResume 方法都会被启动。
在此时的Activity栈中有A、B、C三者存在。其中当前的活动项是位于栈顶位置的C项。其启动模式已经被设置为标准模式。当在当前的C项活动新增一个点击事件时,则会导致另一个相同类型的C项活动被触发。结果会将另一个相同的活动项加入到此stack队列中,并成为新的stack顶端元素。

SingleTop模式(栈顶复用模式)
说明:当需要创建的 Activity 已经位于栈顶端时,在这种情况下可以直接复用栈顶端的那个 Activity ,无需再生成新的活动。相反地,在需要创建但当前该操作未被启动的情况下,则会生成一个新的活动并入栈,并与标准模式的操作保持一致。
在情形一中,当栈顶 Activity 被直接复用时,在其生命周期内将无法触发其 onCreate 和 onStart 方法的行为原因在于该 Activity 未发生任何更改操作。然而,在一个新的场景中(即当该 Activity 正常创建并执行完毕后),将会启动一个新的方法流程以响应新的intent事件触发——即新的方法 onNewIntent 将会得到相应的回调处理。
举例:此时该栈中有三个Activity对象A、B、C,并且当前活动项为C,在这种情况下启动模式被设置为SingleTop模式。第一种情况是在当前活动项C中添加点击事件并将其转发至另一个同类型活动项C'时系统将直接复用当前的活动项。第二种情况则是在当前活动项中添加点击事件但其转发目标为非同类别的另一个活动项A系统则会生成一个新的Activity对象入栈使其取代原来的活动项成为新的栈顶元素

SingleTask模式(栈内复用模式)
当需要创建的 Activity 已经存在于栈中时,在这种情况下不会生成新的 Activity ,而是会销毁栈中位于当前 Activity 上方的所有现有活动,并使当前活动升至栈顶位置。
当调用其他应用程序时,则会创建一个新的 task,并将其包含在其内部运行。此单线程任务支持多个 Activity 在同一时间运行于同一个任务内。即在此单线程任务实例内再次打开另一个 Application 时,该 Application 将继续保留在当前单线程任务执行的状态下。
生命周期阶段:与 SingleTop 模式中第一种情况一致。该活动仅触发一次 onNewIntent 方法。
举例:当前,在该栈中依次存在三个活动实体:包括名称为A、B和C的活动。其中C处于栈顶位置,并采用SingleTask启动模式。第一种情形下,在当前C实体上触发点击事件时,则会切换至另一个相同类型的C实体;操作后的效果即直接采用了当前栈中的顶端C实体。第二种情形下,在当前C实体上触发点击事件时,则会切换至一个位于A实体上方的所有实体;这种情况下会导致所有位于A实体会被销毁并成为新的顶端实体。

SingleInstance模式(单实例模式)
其中一种特殊情况是: SingleInstance 被称为全局单例模式。这种模式进一步强化了 SingleTask 的特性,在其基础上增加了以下两个主要特点:一是拥有单一实例的特点;二是该实例独立运行在一个特定的 task 中,并且该 task 包含唯一的一个实例,在此 task 运行期间不允许有任何其他 Activity 存在。
该应用频繁地被用于系统的各个部分,在软件开发过程中是一个关键组件。具体而言,在整套系统中仅存在一个实现此功能的模块——即Launch以及用于锁屏的操作功能等其他相关模块。因此,在我们的应用场景中通常不会涉及这一功能模块的具体实现细节。掌握即可。
例如,在该模式中使用 A Activity 时, 当启动 A 时, 系统将为此创建一个独立的任务栈. 由于任务栈内的复用特性, 通常情况下, 所有请求都不会生成新的 Activity, 除非相应的独立任务栈被系统销毁.
2.2 启动模式的使用方式

- 在
Manifest.xml中指定Activity启动模式
- 静态的方式进行指定
- 在 Manifest.xml 文件中同时声明 Activity 和其启动模式
- 当代码进行跳转时,在遵循指定模式的基础上创建 Activity
- 启动
Activity时。在Intent中指定启动模式去创建Activity
- 动态启动方案
- 当创建一个新的 Intent 时
- 利用 Intent 的 addFlags 方法灵活设置启动方案。
-
注意:这两种方法均可指定Activity的启动模式;然而它们之间仍存在区别。
优先等级:动态指定的方式相较于第一种而言具有较高的优先等级。若两者同时存在时,则采用另一种方式作为标准。
第一种方式不能直接明确指定 FLAG_ACTIVITY_CLEAR_TOP 标识,并且另一种方式不具备能力以指定 singleInstance 模式
2.3 启动模式的实际应用场景
在这四种模态中,
Standard模态是最常用的一种,
无需特别关注其特性。
而SingleInstance模态属于整个系统的单一实例配置,
在我们的实际应用中通常不会采用。
因此,
本文将重点阐述
SingleTop和SingleTask模态的具体应用场景。

SingleTask模式的运用场景
- 最主要的应用场景是确保我们应用开启后仅有一个
Activity作为实例。 - 最具代表性的例子是应用中的主页( Home 页)。
- 如果一个用户从主页跳转到其他页面并进行多次操作后希望返回 homepage,并且不采用 SingleTask 模式,在点击返回时会反复看到 homepage。这种情况明显反映出设计存在不合理之处。
SingleTop模式的运用场景
- 假设在当前的
Activity中还需要再次启动同类Activity - 此时推荐将此类型
Activity的运行模式设置为SingleTop模式, 从而减少其创建次数并降低内存占用
- 注意:复用
Activity时的生命周期回调
- 此处还需考虑当一个 Activity 在跳转时传递页面参数的情况。
- 由于当一个 Activity 设置了 SingleTop 或者 SingleTask 模式后,在跳转此 Activity 导致原有 Activity 复用的情况下,则该 Activity 的 onCreate 方法将不会再次执行。该方法仅会在第一次创建 Activity 时运行。
- 而通常情况下,在 onCreate 方法中会进行该页面的数据初始化、UI 初始化,并假设如果页面展示数据不依赖于来自跳转传递的参数,则无需担心相关问题。
- 如果一个页面的数据完全依赖于 getInten() 方法获取的话,则会出现问题:因为 getInten() 只能访问已有的数据记录,并不能及时获取最新的数据。
- 以下,通过一个样例来具体解释:

以上代码中的 CourseDetailActivity 在配置文件里设置了运行模式为 SingleTop 模式;参考其运行模式的定义可知,在该类位于栈顶端位置时。
当再次点击跳转到 CourseDetailActivity 时会直接继承原有的 Activity ,并且该页面所需的数据来源于 getIntent() 方法的结果;然而由于 initData() 方法不会被再次执行,则该页面将无法展示最新的数据信息。
显然, 系统早已预见了这种情况. 此时我们需要引入一个回调函数 onNewIntent(Intent intent). 通过该方法的实现, 我们能够解决上述提到的问题. 具体建议的操作步骤是再次调用 setIntent 函数. 接着需要重新初始化数据和 UI 组件. 代码示例如下所示:

- 这样,在一个页面中能够反复跳转并显示不同的内容。
2.4 快速启动一个 Activity

这一问题本质上并不复杂, 其实就是在Activity类的onCreate方法中避免进行过于繁重的操作, 同时也在onPause方法中必须避免进行耗时的操作。
2.5 启动流程
注意!这里并不是要回答 Activity 的生命周期!
2.6 Activity 的 Flags

标记位不仅能够确定Activity的运行模式,在动态指定运行模式时(例如FLAG_ACTIVITY_NEW TASK和FLAG_ACTIVITY_SINGLE_TOP等),此外还能够影响Activity的运行状态(例如FLAG_ACTIVITY_CLEAN_TOP 和 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 等)。
下面介绍一下基本的标记位,请记住一两个就可以,在需要时再查阅官方文档

FLAG_ACTIVITY_NEW_TASK
该Activity通过设置启动模式为"SingleTask"来实现与AndroidMainfest.xml中设定效果一致的功能
FLAG_ACTIVITY_SINGLE_TOP
该Activity被配置为使用'SingleTop'启动模式,并与AndroidMainfest.xml所设定的效果相同。
FLAG_ACTIVITY_CLEAN_TOP
- 当某个带有此标记位的活动启动时,在同一任务栈内会有其他相关活动被弹出。
- 它们通常伴随着 SingleTask 启动模式一起使用。
- 它负责完成 SingleTask 的功能。
- 然而,在 SingleTask 启动模式中,默认情况下并未启用此标记位。
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
- 当一个
Activity设置了此标记位时,在历史Activity列表中将无法显示。 - 此标记位的效果体现在当用户在历史列表中访问某个
Activity时(尤其是当我们不希望他们重新打开该Activity的时候),它起到了关键作用。 - 该标记位的作用等效于在 XML 格式文件中为
Activity设置特定属性。
2.7 onNewInstent()方法什么时候执行

在启动模式中存在这个实例。当此Activity的实例已存在,并且当前启动模式为SingleTask及SingleInstance时,在Stack Top位置运行该Activity实例且启动模式设置为SingleTop时也会调用onNewInstent()。
三、 数据
3.1 Activity 间通过 Intent 传递数据大小限制

我们发现 Intent 在数据传输过程中存在一定的容量限制。官方对此并未明确说明细节信息。通过实验手段测定发现该容量应控制在 1MB 内(换算为 1024KB)。
我们采用了发送 Bitmap 方法进行测试,在图片尺寸达到约 1024 至 1025 单位时观察到程序出现闪退等问题(不同手机的表现略有差异)。
基于上述观察和测试结果分析,在这种情况下我们可以判断 Intent 的传输容量不应超过 1MB。
当内存空间接近耗尽时,系统可能会终止正在运行的所有背景Activity进程。如果希望实现短暂的状态存储功能,则应在相应的类中寻找实现该功能的具体方法。

Activity 中的 onSaveInstanceState() 和 onRestoreInstanceState() 不属于其生命周期方法。与 onCreate() 以及 onPause() 等生命历程的方法不同的是, 它们并不会必然被触发。
该方法会在发生异常情况时(例如内存不足或用户直接按下 Home 键)导致系统销毁其中一个 Activity,并且该方法会被触发。
然而,在用户有意地删除一个 Activity 的情况下(例如在应用界面按回车键),则会使得该方法无法被调用。
只有在 activity 被用户主动销毁的情况下(即 activity 不被用户主动销毁),通常 onSaveInstanceState() 一般仅用于存储短暂的状态信息;而 onPause() 则专门用于实现数据持久化存储。
3.3 onSaveInstanceState() 被执行的场景

- 系统无法预知在按下
HOME时会执行哪些其他程序,并且也无法确定activity A是否会被销毁。- 因此系统会调用
onSaveInstanceState(),以便用户能够保存一些非永久性数据。
- 因此系统会调用
- 当用户触控屏点击
HOME键时 - 当用户长时间触压并选择执行其他应用程序时(在长按
HOME键的同时) - 在锁屏状态下
- 当从活动A切换至新活动
- 在旋转屏幕方向的时候
3.4 两个 Activity 之间跳转时必然会执行的方法

通常情况下假设有两个 Activity 对象分别命名为 A 和 B。当调用 A 的 Begin 方法时 系统会立即触发 A 的 onPause() 方法 并且随后将依次执行 onCreate()、start() 和 onResume() 方法以完成组件的生命周期管理
当下,当 B 占据了窗体时,A 会被触发以执行其 onStop() 方法。如果 B 呈现无色或采用窗口风格,则不会触发 A 的 onStop() 方法。
3.5 用 Intent 去启动一个Activity 之外的方法

- 使用
adb shell am命令
- 启动一个活动时,请使用命令
$am\ start\ com.example.fcheonxuan/.MainActivity$ - 进入控制台并运行命令
$am\ start\ com.example.fcheinovxuan/.MainActivity$ - 请发送一条广播消息,并指定其为
$magcomm.action.TUCH_LETTER$ - 在设备上运行以下命令以发送广播消息并设置其属性值为 magcomm.action.TUCH_LETTER
3.6 scheme 跳转协议

3.6.1 定义

服务器可以定制化跳转 app 页面
app 可以通过 Scheme 跳转到另一个 app 页面
可以通过 h5 页面跳转 app 原生页面
3.6.2 协议格式:


qh 代表 Scheme 协议名称
test 代表 Scheme 作用的地址域
8080 代表改路径的端口号
/goods 代表的是指定页面(路径)
goodsId 和 name 代表传递的两个参数
3.6.3 Scheme使用
- 定义一个
Scheme

- 获取
Scheme跳转的参数

- 调用方式
- 原生调用

- html调用

- 判断某个Scheme是否有效

有关于Schemes传输协议的知识点,在线资源丰富。如需深入了解该协议,请访问相关技术文章。如同站在前人肩膀上就可以看得更远
Android产品研发(11):→ 应用内跳转协议
四、 Context
4.1 Context , Activity , Appliction 的区别

- 相同:Activity和Application都是Context的继承者。
- 在字面上意思上, Context是指上下文的概念;在实际应用中,它确实负责管理着上下文环境中的各种参数和变量,从而使得我们能够方便地访问各种资源。
- 不同: Context负责维护当前Activity的生命周期,而Application则负责维护整个项目的生命周期。
- 使用Context时,请务必小心防止内存泄漏。
4.2 Context 是什么

它描述的是一个应用程序环境的信息,即上下文。
该抽象类本质上是基础性类别,在Android生态系统中基于此实现了基于此的子类构建(ContextIml)。
借助它我们可以访问应用程序的资源和类;这些资源不仅限于类本身还包含一些应用程序级别的功能;具体来说可以通过启动一个Activity实例来实现;此外还可以发布广播消息、处理Intent请求以及接收信息。
4.2.1 附加一张 Context 继承关系图
[图片上传失败...(image-de33df-1572405738902)]
4.3 获取当前屏幕 Activity 的对象

通过配置ActivityLifecycleCallbacks组件,并借助Reflection类获取当前Activity实例对象的唯一标识符
4.4 Activity 的管理机制

面试官问这个问题,想看看大家对Activity了解是否深入:
- 活动记录表是指用于存储和管理各种活动数据的数据结构。
- 任务记录表是指用于存储和管理各种任务数据的数据结构。
- 活动管理服务是指负责协调和管理多个活动以实现组织目标的服务类。
4.5 什么是 Activity

四大主要组成部分之一通常是对应一个activity对象。
activity属于该类别的一个实例并实现了与窗体用户交互事件处理功能。
开发过程中常见的几种是:FragmentActivity、ListActivity和TabActivity(其中Android 4.0已经由Fragment取代)。
五、 进程
5.1 Android 进程优先级
- 前台 / 可见 / 服务 / 后台 / 空

5.1.1 前台进程:Foreground process

该Activity在用户交互时会被激活(启动前处理)。当某个Service被绑定到当前交互中的Activity时,在必要条件下会触发该Service的行为(包括但不限于作为主动服务启动前台应用)。组件在其生命周期阶段被触发进行操作(包括创建时初始化、启动前准备以及销毁时清理),如onCreate表示创建阶段的操作等。该BroadcastReceiver正接收广播消息处理事件。
5.1.2 可见进程:Visible process

- 我们的当前Activity正处于onPause状态(未触发onStop)。
- 该Service已被注册至前台Activity。
5.1.3 服务进程:Service process

- 简单的
startService()启动。
5.1.4 后台进程:Background process

android:process=":xxx".
android:process=":xxx".
5.1.5 空进程:Empty process

不包含任何活动的组件。( Android 设计的,在缓存效果的基础上进行了优化设计。为了第二次启动更快而采取的一种权衡)
5.2 可见进程

可被用户看见的部分程序界面称为可见进程。例如,在界面上显示一个新的对话框(记为 Activity),则该原始界面可视为可见进程。
- 一个进程满足下面任何一个条件都被认为是可视的:
- 被另一个非前台活动寄生(它的
onPause()方法已经被调用)。例如,在某个对话框(由其他进程运行)结束后仍可见的情况中发生(例如输入法弹出时)。 - 被某个服务所寄生(而该服务被绑定到一个可见的操作)。
- 可视进程被认为特别重要,并且只有在需要保护前置进程中才会被终止。
5.3 服务进程

服务进程是由 startService() 方法被触发运行的一类进程。然而,这类进程并不属于前台进程中态或可视进程中态。例如,在运行后台时播放音乐或者下载文件的行为属于服务进程中态。
系统为了维持这些进程运行而持续工作,除非内存不足来支持所有的前台进程和可视进程
5.4 后台进程

后台进程持续进行着一个隐藏状态的操作(已调用指定Activity类的对象onStop()方法)。如果系统中有除UI线程之外的任务运行,则不会受到影响。
我在使用 qq 和别人聊天。此时 qq 是一个前台进程。但当我点击 Home 键关闭后, 它就切换为后台进程。
这些后台进程不会直接影响用户体验,并可在任意时间终止以释放内存供主界面和可视化管理服务进程使用。
通常有大量后台程序在运行状态中,在操作系统 manages them using an LRU 策略(即最近最少使用原则),使得频繁使用的程序始终位于列表末尾以便及时退出。
5.5 空进程

一个未持续存活的应用程序组件被标记为空进程,并且不含任何存活组件
该机制的主要目的是通过缓存机制加快组件重新加载时的性能。为了维持整体系统的稳定运行,在缓存层和内核缓存层之间实施策略性地终止一些不必要的进程。
Android 运行中的各个进程中遵循一定的回收流程依次进行资源释放。具体而言, 从低优先级到高优先级依次回收的是: 无应用运行的进程中, 运行中的后台程序, 作为系统服务运行的进程中, 处于屏幕可见状态的进程中, 最后是当前窗口 foreground application 所使用的资源。
5.6 什么是 ANR,如何避免

5.6.1 什么是ANR

- \texttt{ANR} ,全称是 \texttt{Application Not Responding} 。
- 在 \texttt{Android} 系统中,在你的应用程序长时间未响应时(即长时间未收到响应),系统会向用户展示一个对话框(也被称为应用程序无响应提示),这个提示旨在通知用户当前的应用程序状态。
5.6.2 用户行为

- 用户可以选择决定让程序继续运行或者让它停止运行。
- 他们在使用应用程序时不想每次都处理这个对话框。
- 因此,在程序中合理安排响应性能非常重要。
5.6.3 Android不同组件ANR超时时间不同

各个组件触发ANR事件的时间各不相同;其中主线程(即Activity和Service)的触发时间为5秒;而BroadCastReceiver的触发时间则为10秒。
5.6.4 解决方案

- 将所有高负载操作如网络访问、
Socket通信以及频繁调用的SQL语句执行等复杂任务转移到子线程中进行处理,并通过handler.sendMessage、runonUITread以及AsyncTask等方式向主UI同步显示更新结果, 从而保证用户界面的操作响应效率。 - 如果存在必须等待才能完成的任务, 可在界面上动态展示进度指示, 向用户实时反馈进展状态。
5.7 android的任务栈 Task

- 任务就是一系列activity集合的代表,在Android系统中可以通过task stack实现对这些activity的有效管理
- 通常情况下,并非所有应用都只拥有单个task stack;特别地,在单实例模式启动的应用中会拥有独立的任务栈
总结
- 本文全面介绍了 Android 活动的核心内容和相关知识要点。希望各位能够通过参考文章中的链接或在 Google 上自行搜索相关信息来深入学习 App 启动和 AMS 相关内容。
- 重点阐述了 Android 的四大组件之一——Activity的相关知识和操作流程。经过本次的学习和实践后,在Activity部分已经掌握了许多关键点,并且已经完成了对Activity的全面总结。下一步计划是针对Service、BroadcastRecevier等组件以及事件分发、滑动冲突和新功能优化等内容进行详细讲解。
如需进一步了解相关内容,请访问 yuanhao 的 简书(https://www.jianshu.com/u/dfdd57aee7df)以获取最新更新信息。
码字不易,你的点赞是我总结的最大动力!
我目前活跃于「稀土掘金」、「简书」以及「``」等平台,并定期在这些渠道发布最新资讯。因此,请大家通过关注我的GitHub仓库获取最新的研究成果与资源!
仓库地址:
超级干货!精心归纳 Android 、JVM 、算法等,各位帅气的老铁支持一下!给个 Star !
这篇冗长的文字内容搭配上精美的思维导图,请您务必给予关注与支持
