ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

YCBlogs 之 Activity 完全指南:生命周期、启动模式与任务栈深度解析

YCBlogs 之 Activity 完全指南:生命周期、启动模式与任务栈深度解析 教程技术博客文档【免费下载链接】YCBlogs技术博客笔记大汇总包括Java基础线程并发数据结构Android技术博客等等常用设计模式常见的算法网络协议知识点部分flutter笔记还包括平时开发中遇到的bug汇总当然也在工作之余收集了大量的面试题长期更新维护并且修正持续完善……开源的文件是markdown格式的转载请注明出处谢谢项目地址https://gitcode.com/gh_mirrors/yc/YCBlogs点击查看免费下载导读本文以 YCBlogs 仓库中 android/01.基础组件/02.Activity基础介绍.md 为核心骨架系统梳理 Android 四大基础组件之首 —— Activity 的生命周期、异常场景处理、四种启动模式与任务栈机制。通过结合仓库中 03.Activity启动流程.md 的 AOSP 源码调用链分析与 question/android/01.Android之基础组件问题.md 的面试题沉淀读者将完整掌握七大生命周期方法的正确使用姿势、屏幕旋转与内存回收等异常场景的保命方案、四种启动模式的选型依据以及任务栈Task交互的底层逻辑可直接应用于日常开发与面试准备。一、Activity 生命周期全解析1.1 七大生命周期方法说明在正常情况下一个 Activity 从启动到结束会以如下顺序经历整个生命周期onCreate()当 Activity 第一次创建时被调用是生命周期的第一个方法。在此方法中做初始化工作比如调用setContentView加载界面布局资源、初始化 Activity 所需的数据。也可以借助 onCreate 的 Bundle 参数来恢复异常情况下 Activity 结束时的状态详见后文。onRestart()表示 Activity 正在重新启动。当 Activity 从不可见重新变为可见状态时被调用一般由用户行为导致——例如用户按 Home 键切换到桌面或打开另一个新 Activity之后又回到当前 Activity。onStart()表示 Activity 正在被启动、即将开始此时 Activity 已经出现但还没有出现在前台无法与用户交互。可以理解为Activity 已经显示出来但是我们还看不到。onResume()表示 Activity已经可见并且出现在前台并开始活动。需要与 onStart 对比记忆onStart 时 Activity 还在后台onResume 时才显示到前台。onPause()表示 Activity 正在停止仍可见正常情况下紧接着 onStop 就会被调用。特殊情况下如果此时快速回到当前 ActivityonResume 会被调用极端情况。onPause 中不能进行耗时操作会影响到新 Activity 的显示——因为 onPause 必须执行完新的 Activity 的 onResume 才会执行。onStop()表示 Activity 即将停止、不可见、位于后台。可以做稍微重量级的回收工作同样不能太耗时。onDestroy()表示 Activity 即将销毁是生命周期最后一个回调可以做回收工作和最终资源释放。在平常的开发中最常用的是onCreate()和onDestroy()分别做初始化与回收操作。补充理解源码视角为什么 onPause 里不能做耗时操作结合 03.Activity启动流程.md 中对旧版 AOSP 源码的调用链分析可以更直观地看到启动一个新 Activity 时SystemServer 进程会先通过startPausingLocked()让栈顶旧 Activity 执行 onPause链路为ActivityStack.startPausingLocked()→IApplicationThread.schedulePauseActivity()→ActivityThread.H.sendMessage()→handlePauseActivity()→performPauseActivity()→Instrumentation.callActivityOnPause()→Activity.performPause()→Activity.onPause()。只有当旧 Activity 的 onPause 执行完并通过activityPaused()通知服务端后AMS 才会继续resumeTopActivitiesLocked()去启动新的 Activity。因此 onPause 中的耗时操作会直接阻塞新页面的展示。1.2 Activity 三种运行状态Activity 的运行状态与进程优先级划分一一对应共三种① Resumed活动状态又叫 Running 状态。Activity 正在屏幕上显示并且拥有用户焦点即用户正在操作的那个界面优先级最高。② Paused暂停状态比较不常见。Activity 在屏幕上是可见的但并不是屏幕最前端的那个 Activity。例如另一个非全屏或透明的 Activity 处于 Resumed 状态没有完全遮盖当前 Activity。③ Stopped停止状态Activity 完全不可见时进入此状态Activity 仍在后台运行内存中仍保留 Activity 的状态并没有完全销毁。例如跳转到另外一个界面后之前的界面还在后台按回退按钮还会恢复原来的状态大部分 App 按 Home 键并不会被关闭此时就是 Stopped 状态。1.3 App 切换到后台分析针对后台切换这一高频场景原文档给出了三个关键结论App 切换到后台当前 Activity 会走 onDestroy 吗不会。会先后走onPause和onStop方法Activity 实例与状态仍然保留在任务栈与内存中。一般在 onStop 方法里做什么写轮播图时在onStop中暂停轮播图无限轮播在onStart中开启自动无限轮播写视频播放器时当 App 切换到后台需要在onStop中停止视频播放。什么情况会导致 App 被杀死被杀死时会走 onDestroy 吗系统资源不足会导致 App 意外被杀死。应用只有在进程存活的情况下才会按照正常生命周期执行如果进程被突然 kill 掉相当于System.exit(0)进程被杀死后根本不会走 Activity/Fragment 的生命周期。只有在进程不被 kill 掉的正常情况下才会执行 onDestroy。二、特殊情况下的生命周期2.1 情况一销毁后重建横竖屏切换在横竖屏切换过程中Activity 会经历销毁并重建的过程这种场景应尽量避免。理解该场景需要先掌握两个回调onSaveInstanceState 和 onRestoreInstanceState。当 Activity 由于异常情况非人为终止时系统会调用onSaveInstanceState来保存当前 Activity 的状态。该方法的调用在onStop 之前与 onPause 没有既定的时序关系它只在 Activity 被异常终止的情况下调用。当异常终止的 Activity 被重建以后系统会调用onRestoreInstanceState并把 Activity 销毁时 onSaveInstanceState 保存的 Bundle 对象同时传递给 onRestoreInstanceState 和 onCreate 方法。恢复状态可以通过onRestoreInstanceState方法完成其调用时机在onStart 之后。onCreate 与 onRestoreInstanceState 恢复状态的区别onRestoreInstanceState 回调时其中的 Bundle 对象非空不用加非空判断而 onCreate 中的 savedInstanceState 可能为 null需要非空判断。官方建议优先使用 onRestoreInstanceState。2.2 情况二不销毁通过配置属性接管比如视频播放器经常涉及屏幕旋转场景可以通过在 AndroidManifest 的 Activity 中指定如下属性避免横竖屏切换时 Activity 被销毁重建activity android:name.activity.VideoDetailActivity android:configChangesorientation|keyboardHidden|screenSize android:screenOrientationportrait/配置了configChanges后旋转屏幕不再销毁重建 Activity而是回调下面的方法// 重写旋转时方法不销毁 activity Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); }实践要点configChanges需要按需声明。若只声明orientation在 Android 3.2API 13及以上系统上旋转屏幕仍可能重建 Activity——因为系统还会检测screenSize的变化所以通常需要同时声明orientation|screenSize原文档中同时包含了keyboardHidden用于避免键盘隐藏状态变化触发重建。如果业务确实需要响应配置改变就在声明 configChanges 后重写onConfigurationChanged自行处理。2.3 情况三内存不足导致低优先级 Activity 被杀死Activity 优先级划分与 1.2 节三种运行状态对应前台 Activity——正在和用户交互的 Activity优先级最高可见但非前台 Activity——比如 Activity 中弹出了一个对话框导致 Activity 可见但位于后台无法与用户交互后台 Activity——已经被暂停的 Activity比如执行了 onStop优先级最低。当系统内存不足时会按照上述优先级从低到高去杀死目标 Activity 所在的进程。这种情况下数据的保存与恢复过程与横竖屏切换一致生命周期情况也一样——即先回调onSaveInstanceState保存状态重建后通过onRestoreInstanceState/onCreate恢复。如何判断 Activity 的优先级除了栈顶的 Activity其他 Activity 都有可能在内存不足时被系统回收Activity 越处于栈底被回收的可能性越大。如果有多个后台进程系统在选择杀死的目标时采用最近最少使用算法LRU。三、Activity 启动模式与任务栈3.1 启动模式的类别与结构Android 提供了四种 Activity 启动方式模式名称核心行为standard标准模式每次启动都创建新实例singleTop栈顶复用模式栈顶已存在时复用并回调 onNewIntentsingleTask栈内复用模式栈内存在即复用并回调 onNewIntentsingleInstance单例模式独占一个任务栈全局唯一实例Activity 的管理采用**任务栈Task**形式任务栈采用后进先出LIFO的栈结构。任务栈Task的本质Google 对 Task 的定义是——Task 实际上是一个 Activity 栈通常用户感知的一个 Application 就是一个 Task。从这个定义看Task 与 Service 或其他组件没有任何联系它只是针对 Activity 而言的。可通过getTaskId()获取任务栈的 ID如果前面的任务栈已经清空新开的任务栈 ID 会自动 1 递增。3.2 standard 标准模式每启动一次 Activity就会创建一个新的 Activity 实例并置于栈顶。谁启动了这个 Activity那么这个 Activity 就运行在启动它的那个 Activity 所在的栈中。例如 Activity A 启动 Activity B则会在 A 所在的栈顶压入一个新的 Activity。特殊场景如果在 Service 或 Application 中启动一个 Activity它们没有所谓的任务栈可以使用标记位 Flag 解决——为待启动的 Activity 指定FLAG_ACTIVITY_NEW_TASK标记位创建一个新栈。应用场景与跨进程行为绝大多数 Activity 使用此模式。如果以 standard 方式启动的 Activity 被跨进程调用在Android 5.0 之前新启动的 Activity 实例会放入发送 Intent 的 Task 的栈顶尽管它们属于不同的程序这种设计看起来不太合理Android 5.0 及之后上述情景会创建一个新的 Task新启动的 Activity 放入刚创建的 Task 中更加合理。3.3 singleTop 栈顶复用模式如果需要新建的 Activity 位于任务栈栈顶那么该 Activity 的实例不会重建而是重用栈顶实例并回调onNewIntentOverride protected void onNewIntent(Intent intent) { super.onNewIntent(intent); }由于不会重建 Activity 实例不会回调其他生命周期方法。如果栈顶不是新建的 Activity就会创建该 Activity 的新实例并放入栈顶。应用场景通知栏点击收到的通知需要启动一个 Activity该 Activity 可用 singleTop否则每次点击都会新建一个 Activity 实例解决连续快速点击启动两个 Activity的 bug如果待启动的 Activity 使用 singleTop 模式可以避免重复创建与 standard 相同如果是外部程序启动 singleTop 的 ActivityAndroid 5.0 之前新创建的 Activity 位于调用者的 Task 中5.0 及以后会放入新的 Task 中。3.4 singleTask 栈内复用模式该模式是一种单例模式——一个栈内只有一个该 Activity 实例。singleTask 可以与taskAffinity配合使用指定开启的 Activity 加入到哪个栈中activity android:name.Activity1 android:launchModesingleTask android:taskAffinitycom.yc.task android:labelstring/app_name /activity关于 taskAffinity 的值每个 Activity 都有 taskAffinity 属性指出它希望进入的 Task。如果 Activity 没有显式指明 taskAffinity该属性就等于 Application 指明的 taskAffinity如果 Application 也没有指明那么该值就等于包名。这个属性也可以不设置。执行逻辑如果 Activity 指定的栈不存在则创建一个栈并把创建的 Activity 压入栈内如果 Activity 指定的栈存在栈中没有该 Activity 实例 → 创建 Activity 并压入栈顶栈中有该 Activity 实例 →把该 Activity 实例之上的 Activity 全部杀死清除出栈重用并让该实例处于栈顶然后调用onNewIntent()方法。应用场景大多数 App 的主页。当我们在主界面点击回退按钮时通常就是退出应用。第一次进入主界面后主界面位于栈底之后无论打开了多少个 Activity再次回到主界面时都应该将主界面之上所有 Activity 移除、让主界面处于栈顶而不是往栈顶新加一个主界面实例——这样能保证退出应用时所有 Activity 都被销毁。跨应用 Intent 传递时如果系统中不存在 singleTask Activity 的实例那么将创建一个新的 Task再创建 singleTask Activity 实例放入新 Task 中。典型案例浏览器主界面。不管从多少个应用启动浏览器只会启动主界面一次其余情况都会走onNewIntent并且会清空主界面上面的其他页面。3.5 singleInstance 单例模式作为栈内复用模式singleTask的加强版打开该 Activity 时直接创建一个新的任务栈并创建该 Activity 实例放入新栈中。一旦该模式的 Activity 实例已经存在于某个栈中任何应用再激活该 Activity 时都会重用该栈中的实例。应用场景呼叫来电界面。这种模式的使用情况比较罕见在 Launcher 中可能使用。只有确定需要使 Activity 只有一个实例时才考虑使用建议谨慎使用。3.6 Activity 的 FlagsActivity 的 Flags 很多这里介绍几个常用的、用于设定 Activity 启动模式的 Flag可以在启动 Activity 时通过 Intent 的addFlags()方法设置① FLAG_ACTIVITY_NEW_TASK其效果与指定 Activity 为 singleTask 模式一致② FLAG_ACTIVITY_SINGLE_TOP其效果与指定 Activity 为 singleTop 模式一致③ FLAG_ACTIVITY_CLEAR_TOP具有此标记位的 Activity 启动时在同一个任务栈中所有位于它上面的 Activity 都要出栈。如果与 singleTask 模式一起出现被启动的 Activity 已存在栈中时清除其之上的 Activity并调用该 Activity 的 onNewIntent 方法如果被启动的 Activity 采用 standard 模式该 Activity 连同之上的所有 Activity 出栈然后创建新的 Activity 实例并压入栈中。同一程序不同的 Activity 是否可以放在不同的 Task 任务栈中可以使用 singleInstance 启动模式Activity 可以运行在另外的单独任务栈中该 Activity 在内存中只有一份不会重复开启也可以在激活一个新的 Activity 时给 Intent 设置 Flag——添加FLAG_ACTIVITY_NEW_TASK被激活的 Activity 就会在新的 Task 栈中。3.7 特殊情况栈交互前台栈与后台栈假如目前有两个任务栈前台任务栈为 AB后台任务栈为 CD假设 CD 的启动模式均为 singleTask请求启动 D后台任务栈整个被切换到前台此时整个后退列表变成ABCD。当用户按 back 返回时列表中的 Activity 会一一出栈。请求启动 C情况又不一样——调用 singleTask 模式的后台任务栈中的 Activity会把整个栈的 Activity 压入当前栈的栈顶同时 singleTask 具有 clearTop 特性会把该 Activity 之上的栈内 Activity 清除。小结singleTask 模式的全局唯一 clearTop 清栈特性是跨 Task 交互时栈结构发生变化的核心原因。四、Activity 异常情况状态保存与恢复4.1 异常生命周期异常条件会调用什么方法当非人为终止 Activity 时系统配置发生改变导致 Activity 被杀死并重新创建、资源内存不足导致低优先级 Activity 被杀死会调用onSaveInstanceState()保存状态。该方法调用在onStop 之前但与 onPause 没有时序关系。onSaveInstanceState() 与 onPause() 的区别onSaveInstanceState 适用于临时性状态的保存onPause 适用于数据的持久化保存。当异常崩溃后 App 又重启会走onRestoreInstanceState()方法可以在此方法中取出 onSaveInstanceState 保存的状态数据。什么时候会引起异常生命周期资源相关的系统配置发生改变或资源不足例如屏幕旋转当前 Activity 会销毁并在 onStop 之前回调 onSaveInstanceState 保存数据重新创建 Activity 时在 onStart 之后回调 onRestoreInstanceState。其中 Bundle 数据会传到 onCreate不一定有数据和 onRestoreInstanceState一定有数据。异常导致 App 崩溃但进程没有被完全杀死重启回到 Activity 页面也会引起异常生命周期。4.2 后台 Activity 被异常回收回收后怎么办Activity 提供了onSaveInstanceState()回调方法该方法保证一定在 Activity 被回收之前调用可解决 Activity 被回收时临时数据得不到保存的问题。onSaveInstanceState 携带一个 Bundle 类型参数Bundle 提供了一系列保存数据的方法例如putString()保存字符串、putInt()保存整型数据。每个保存方法需要传入两个参数第一个是键用于从 Bundle 中取值第二个是真正要保存的内容。onSaveInstanceState() 和 onRestoreInstanceState() 的特点这两个方法并不是生命周期方法不同于 onCreate、onPause 等生命周期方法它们并不一定会被触发。示例代码如下// 保存数据 Override protected void onSaveInstanceState(Bundle outBundle) { super.onSaveInstanceState(outBundle); outBundle.putBoolean(Change, mChange); } // 取出数据 Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState); mChange savedInstanceState.getBoolean(Change); } // 或者在 onCreate 方法取数据也可以 // onCreate() 方法其实也有一个 Bundle 类型的参数。这个参数在一般情况下都是 null // 但是当 Activity 被系统回收之前通过 onSaveInstanceState() 方法保存过数据的话 // 这个参数就会带有之前所保存的全部数据 Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (savedInstanceState ! null) { String data savedInstanceState.getString(data); } }什么时候会触发这两个方法当应用遇到意外情况如内存不足、用户直接按 Home 键由系统销毁一个 Activity 时onSaveInstanceState()会被调用当用户主动销毁一个 Activity 时例如在应用中按返回键onSaveInstanceState()不会被调用除非 Activity 是被用户主动销毁的否则 onSaveInstanceState 只适合用于保存临时性状态onPause 适合用于数据持久化保存。onSaveInstanceState() 被执行的场景系统不知道按下 HOME 后要运行多少其他的程序自然也不知道 Activity A 是否会被销毁因此系统都会调用onSaveInstanceState()让用户有机会保存某些非永久性数据。以下场景都遵循该原则按下 Home 键时长按 Home 键选择运行其他程序时锁屏时从 Activity A 中启动一个新的 Activity 时屏幕方向切换时。4.3 屏幕旋转时的生命周期对比屏幕旋转时如果不做任何处理Activity 会经历销毁到重建的过程一般这种效果都不是想要的视频播放器就经常涉及屏幕旋转场景。第一种情况当前 Activity 不销毁。设置android:configChangesorientation|keyboardHidden|screenSize后切屏不会重新调用各个生命周期只会执行onConfigurationChanged方法activity android:name.activity.VideoDetailActivity android:configChangesorientation|keyboardHidden|screenSize android:screenOrientationportrait/// 重写旋转时方法不销毁 activity Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); }第二种情况销毁当前 Activity 后重建应尽量避免。不设置android:configChanges时切屏会重新调用各个生命周期——默认首先销毁当前 Activity然后重新加载。4.4 两个经典问题如何避免重建、如何恢复状态问题一如何避免配置改变时 Activity 重建在 AndroidManifest.xml 中对应的 Activity 设置android:configChangesorientation|screenSize。此时再次旋转屏幕该 Activity 不会被系统杀死和重建只会调用onConfigurationChanged。因此当程序需要响应配置改变时指定 configChanges 属性、重写 onConfigurationChanged 方法即可。典型使用场景视频播放器横竖屏切换播放视频。问题二优先级低的 Activity 在内存不足被回收后怎样恢复到销毁前状态优先级低的 Activity 在内存不足被回收后重新打开会引发 Activity 重建。Activity 被重新创建时会调用onRestoreInstanceState在 onStart 之后并将 onSaveInstanceState 保存的 Bundle 对象作为参数传到 onRestoreInstanceState 与 onCreate 方法。因此可通过这两个方法判断 Activity 是否被重建并取出数据恢复。注意在 onCreate 取出数据时一定要先判断 savedInstanceState 是否为空。五、启动模式与生命周期的源码级印证5.1 启动流程中的关键调用链结合仓库 03.Activity启动流程.md可以印证本文第一部分为什么 onPause 先于新 Activity 的 onCreate/onResume的结论。完整启动流程基于旧版 AOSP 源码大致为MyActivity.startActivity() → Activity.startActivity() → Activity.startActivityForResult() → Instrumentation.execStartActivity() → ActivityManagerNative.getDefault().startActivityAsUser() → ActivityManagerService.startActivity() → ActivityStackSupervisor.startActivityMayWait() → ... → startPausingLocked() // 让旧 Activity 执行 onPause → IApplicationThread.schedulePauseActivity() → ActivityThread.handlePauseActivity() → performPauseActivity() → callActivityOnPause() → onPause() → 应用进程通知 AMS activityPaused() → resumeTopActivitiesLocked() → startSpecificActivityLocked() → 进程未启动则 startProcessLocked() 启动进程 → attachApplicationLocked() → realStartActivityLocked() → scheduleLaunchActivity() → handleLaunchActivity() → performLaunchActivity() → callActivityOnCreate() → onCreate() → activity.performStart() → onStart() → handleResumeActivity() → performResumeActivity() → onResume()几个值得记忆的源码细节引用自 03.Activity启动流程.mdActivity 的创建是反射完成的performLaunchActivity中通过mInstrumentation.newActivity(cl, component.getClassName(), r.intent)以反射机制创建 Activity 实例startActivity 内部就是 startActivityForResultstartActivity(intent)最终调用startActivityForResult(intent, -1)且只有requestCode 0时onActivityResult才会被回调——这解释了为什么普通 startActivity 不会收到结果Instrumentation 的角色Instrumentation 是 Activity 在应用进程端启动的实际操作类应用进程端与 SystemServer 服务进程端相互配合最终完成 Activity 在系统中的启动Binder 双向通信通过ActivityManagerNative → ActivityManagerService实现应用进程到 SystemServer 进程的通信通过ApplicationThread → IApplicationThread实现 SystemServer 进程到应用进程的通信。5.2 从 Launcher 到启动模式的系统背景结合 03.Activity启动流程.md 中 Launcher 的启动分析Launcher 中点击应用图标执行startActivity(intent)Intent 通过setClassName(packageName, className)组装Launcher 使用隐式启动的原因Launcher 与应用不在同一进程无法引用到目标 Activity 的字节码只能通过 Intent 携带的组件信息交给系统解析应用图标与 Launcher Activity 的关联系统启动时启动 PackageManagerService包管理服务解析应用的 AndroidManifest.xml 得到所有组件信息Launcher 查询包含MAIN LAUNCHERintent-filter 的 Activity 并为每个创建一个快捷图标intent-filter action android:textandroid.intent.action.MAIN / category android:textandroid.intent.category.LAUNCHER / /intent-filter而整个应用进程的诞生可以追溯到 00.App启动流程梳理.md 中的进程链init 进程 → Zygote 进程 → SystemServer 进程 → 各种应用进程。Activity 的启动请求最终交由运行在 SystemServer 进程中的 ActivityManagerService 统筹调度。六、面试要点速查以下要点综合了原文档末尾的问答总结与仓库 question/android/01.Android之基础组件问题.md 中沉淀的面试题是 Activity 主题的高频考点6.1 四种启动模式一句话概括standard 标准模式每次启动一个 Activity 就会创建一个新的实例singleTop 栈顶复用模式如果新 Activity 已位于任务栈栈顶不会重新创建并回调onNewIntent(intent)singleTask 栈内复用模式只要该 Activity 在一个任务栈中存在都不会重新创建并回调onNewIntent(intent)如果不存在系统先寻找是否存在需要的栈——不存在则创建新任务栈并放入存在则创建到已存在的栈中singleInstance 单实例模式具有此模式的 Activity 只能单独位于一个任务栈中且此任务栈中只有唯一一个实例。6.2 singleTop 和 singleTask 的区别及应用场景对比项singleTopsingleTask实例数量同个 Activity 实例在栈中可以有多个可能重复创建同个 Activity 实例在栈中只有一个不存在重复创建任务栈默认进入启动它所属的任务栈不引起任务栈变更可通过android:taskAffinity设定需要的任务栈可能引起任务栈变更典型场景防止快速点击时多次 startActivity通知栏跳转、快速点击防抖主页、登录页onNewIntent 回调时机singleTop新 Activity 已位于任务栈栈顶不会重新创建回调onNewIntent(intent)singleTask只要该 Activity 在一个任务栈中存在都不会重新创建回调onNewIntent(intent)。6.3 任务栈的作用任务栈存放 Activity 的引用Activity 不同的启动模式对应不同的任务栈存放方式可通过getTaskId()获取任务栈 ID前面的任务栈已清空时新开任务栈 ID 自动 1 递增。Task 是 Google 定义的 Activity 栈用户感知的一个 Application 就是一个 TaskTask 与 Service 等其他组件没有联系只针对 Activity 而言。6.4 App 切后台与进程被杀App 切后台Activity 走onPause→onStop不会走 onDestroyonStop 中可做轮播暂停、视频停止播放等操作系统资源不足导致进程被 kill相当于System.exit(0)不会走任何 Activity/Fragment 生命周期方法Activity 被回收恢复覆写onSaveInstanceState()将状态数据存入 Bundle重建时该 Bundle 作为参数传给 onCreate取出数据恢复到被销毁前的状态。6.5 异常场景必背结论屏幕旋转未处理 configChanges先onSaveInstanceStateonStop 之前保存数据销毁重建后onRestoreInstanceStateonStart 之后恢复Bundle 数据传往两处onCreate不一定有数据需判空和 onRestoreInstanceState一定有数据无需判空建议优先用 onRestoreInstanceState避免重建android:configChangesorientation|screenSize 重写onConfigurationChanged进程被回收的优先级判断除栈顶外都可能被回收越靠近栈底回收可能性越大多后台进程时采用 LRU 算法选择被杀目标。总结Activity 作为 Android 四大组件之首其生命周期、启动模式与任务栈机制构成了应用页面管理的基础。本文以 02.Activity基础介绍.md 为骨架完整覆盖了七大生命周期方法、三种运行状态、后台切换行为、屏幕旋转与内存回收等异常场景、四种启动模式及其 Flags、前后台任务栈交互并借助仓库内 03.Activity启动流程.md 的 AOSP 调用链分析印证了onPause 先于新页面显示等关键结论。开发者在实践中应记住三条主线onPause/onStop 不做耗时操作、异常场景用 onSaveInstanceState/onRestoreInstanceState 保存恢复临时状态、根据页面角色主页/通知页/来电页选择正确的启动模式。如需进一步深入可继续阅读仓库内关联文档03.Activity启动流程.md启动调用链源码分析、00.App启动流程梳理.mdZygote 与 SystemServer 进程、01.ActivityThread分析.md应用进程主线程入口、question/android/01.Android之基础组件问题.md更多基础组件面试题。赞分享教程技术博客文档【免费下载链接】YCBlogs技术博客笔记大汇总包括Java基础线程并发数据结构Android技术博客等等常用设计模式常见的算法网络协议知识点部分flutter笔记还包括平时开发中遇到的bug汇总当然也在工作之余收集了大量的面试题长期更新维护并且修正持续完善……开源的文件是markdown格式的转载请注明出处谢谢项目地址https://gitcode.com/gh_mirrors/yc/YCBlogs点击查看免费下载相关推荐YCBlogs生命周期管理深入理解Android组件生命周期YCBlogs生命周期管理深入理解Android组件生命周期 在Android开发中Activity和Fragment的生命周期管理是构建稳定、高效应用的基教程技术博客文档免费DX7 FM合成器终极指南Dexed让你的音乐制作焕然一新免费DX7 FM合成器终极指南Dexed让你的音乐制作焕然一新 你是否梦想拥有Yamaha DX7那标志性的80年代FM合成音色却不想花费数千元购买古董硬件音视频CANN/GE aclmdlQuerySize函数aclmdlQuerySizea nameZH CN_TOPIC_0000001312641793 /a 产品支持情况a namesection人工智能深度学习模型编译模型优化编译器Ascend上一篇NVIDIA NeMo Checkpoint 格式全解析.nemo、.ckpt、.safetensors 与分布式 Checkpoint 的保存、恢复与实战应用下一篇TiKV HTTP API 指南基于 Status Server 的 CPU / Heap Profiling 与符号解析实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表