关于Activity中onStop和onPause调用时机的各种误解

本文深入研究了Android Activity的生命周期,特别是在不同场景下onPause和onStop方法的调用时机。通过对特定条件的测试,澄清了常见误解,并提供了一个可复现的例子。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

源码 : https://github.com/w-g-b/ActivityReview

正确结果

假设当前的FirstActivity为A,要调用A的onPause方法而不调用onStop方法

 

1. 在AndroidManifest文件中,将ThirdActivity(B)的theme属性设置为对话框样式(也可以使用自定义主题,也不必一定是对话框,也可以设置成透明样式的Activity)

2. 在A中通过startActivity启动B,这个时候就只会调用A的onPause方法,并会调用B的onCreate,onStart,onResume方法

3. 关闭B时,只会重新调用A的onResume方法

目前我的测试也就只有这种情况下才会只调用A的onPause方法,而不调用onStop方法

 而会调用onStop方法的情况则比较多,比如: 锁屏,按Home返回桌面,来电,或者像微信PC端请求登录时,客户端突然蹦出现的确定信息 ,都会调用onStop方法

有关onStop和onPause时机的各种误解

网上很多人说,当弹出对话框时会调用onPause方法或者说活动可见但被遮挡而不能交互时,会调用onPause,所以做了如下的测试,证明这种说法是错的

1. 当发生弹窗,或者弹吐司(Toast)的时候,并不会调用onPause方法

2. 当有新消息,比如说新短信提醒或者像微信那种新信息提示时,也不会调用onPause方法

3. 这个也是有利的证据,下拉Android系统自带的通知栏,此时当前Activity被遮挡,并且无法进行交互,但是仍然没有调用onPause方法

而关于onStop的说法是,当Activity不可见的时候会调用onStop方法,这里也举个反例。通过将对话框主题的Activity设置为全屏并且是可见的,观看打印结果

这里使用自定的对话框样式:

1. 在模块/src/main/res/values/styles.xml添加一个新的样式:

2. AndroidManifest中设置该theme

3. 代码中实现全屏

4. 如果说状态栏还在有影响,则可以添加如下代码,隐藏掉状态栏

5. 此时,启动该对话框样式的Activity则是全屏的,完全遮挡了后面的Activity

6. 此时的打印信息,仍只会调用前面那个Activity的onPause方法

 另外还有一种比较神奇的现象:就算是跳到其他页面,使得该Activity完全不可见,也不会调用该的onPause, onStop方法

1. 首先得是MIUI系统,其他系统我不清楚有没有这功能

2. 使用系统自带的截图功能截图,此时会截完图会出现一个缩略图在右上角展示

3. 点击缩略图跳转,进入图片处理界面,此时改界面完全遮盖了原有的Activity

4. 按返回键返回原来的界面

在这整个过程当中,并不会调用onPause或者onStop方法。

当然,如果你在图片处理界面点击了发送或者美化,才会开始调用原Activity的onPause和onStop方法

感觉网上的信息真的是太多太复杂了,不一定可信,还是需要自己亲自测试一下,才能验证结果。代码已上传,详解上面的github链接↑↑↑ 

<think>我们正在讨论DecorView在Activity生命周期中与onStop方法的关联。用户的问题集中在DecorView的创建与加载流程ActivityonStop方法之间有什么联系。我们需要结合Android的窗口管理Activity生命周期来回答。 首先,回顾一下DecorView的创建加载流程: 1. 当Activity启动时,系统会创建Activity对象,并调用其onCreate方法。在onCreate方法中,我们通常会调用setContentView,这个方法会触发DecorView的创建布局的加载(引用[1][2])。 2. 在setContentView中,PhoneWindow会创建DecorView,并将用户提供的布局添加到DecorView的内容父布局中。 3. 然后,在Activity的onResume方法之后,Activity会变得可见。在这个过程中,ActivityThread会调用handleResumeActivity方法,该方法会将DecorView添加到WindowManager中(即通过WindowManager.addView方法),此时ViewRootImpl被创建并与DecorView关联(引用[3])。 现在,我们考虑onStop方法: - onStop方法在Activity不再对用户可见时调用。这通常发生在另一个Activity覆盖了当前Activity,或者用户按了Home键回到主屏幕等情况。 DecorView与onStop的联系: 1. 当Activity进入onStop状态时,系统会通知WindowManager移除该Activity的窗口(即DecorView)。但注意,这并不意味着DecorView被销毁,而是从窗口系统中分离(detach),使其不可见。 2. 在ActivityonStop方法被调用之前,系统会先调用onPause。在onPause之后,Activity的窗口会被移除。具体来说,ActivityThread会调用handleStopActivity方法,该方法会依次调用ActivityonStop,然后可能会将窗口从WindowManager中移除(但注意,移除窗口的时机可能因版本情况而异)。 具体流程: - 当Activity需要停止时,ActivityManagerService会通知ActivityThread执行Activity的停止操作。 - 在ActivityThread的handleStopActivity方法中,会先调用ActivityonStop方法,然后调用ActivityonStop方法之后,会调用Activity的performStop方法,最后可能会调用WindowManagerGlobal.removeView方法,该方法会移除DecorView(即销毁ViewRootImpl并断开与Surface的连接)。 因此,DecorView在onStop时的处理: 1. 在onStop中,DecorView会被从窗口系统中移除,即调用WindowManager.removeView,这会导致ViewRootImpl的die方法被调用,进而触发ViewRootImpl的doDie方法,最终会移除DecorView并释放相关资源(如Surface)。 2. 此时,DecorView虽然可能还存在于内存中(因为Activity实例还没有被销毁),但它已经不再与WindowManager关联,也不再显示。 注意:在配置变更(如旋转屏幕)时,Activity会经历销毁重建,此时DecorView也会被销毁,然后重新创建。但在正常的生命周期中(比如被其他Activity覆盖),onStop只会导致DecorView被移除,但Activity实例DecorView实例可能仍然保留,直到Activity被销毁(onDestroy)。 总结关联点: - 创建:DecorView在Activity的onCreate中通过setContentView创建(但此时还未附加到窗口)。 - 附加:在onResume中,DecorView被附加到WindowManager,此时ViewRootImpl被创建,并开始视图的绘制流程,使Activity可见。 - 移除:在onStop中(确切地说,在onStop之后),DecorView被从WindowManager中移除,导致其不可见,并且相关的绘制事件接收停止。 引用说明: - 引用[1]说明了DecorView的创建布局加载发生在setContentView时。 - 引用[2]说明了onCreate是Activity生命周期的开始,我们在这里设置布局。 - 引用[3]说明了在handleResumeActivity中,Activity的onResume被调用,并且DecorView被添加到窗口管理器。 因此,DecorView与onStop的联系在于:当Activity进入onStop状态时,DecorView会被从窗口系统中移除,从而不再可见,也不再接收输入事件绘制。 相关问题: 1. 在ActivityonStop方法中,DecorView是否立即被移除? 2. Activity进入onStop状态后,DecorView的资源会被释放吗? 3. 当ActivityonStop状态恢复(onRestart)时,DecorView如何重新附加? 4. 为什么在onStop中移除DecorView而不是在onPause中?</think>### DecorView创建流程与Activity生命周期中onStop方法的关联分析 #### 1. **DecorView创建的核心时机** DecorView的创建发生在Activity生命周期的**onCreate阶段**: ```mermaid sequenceDiagram participant A as ActivityThread participant B as PhoneWindow participant C as DecorView A->>B: 创建PhoneWindow对象 B->>C: 生成DecorView容器 A->>C: setContentView()加载布局 C->>C: 将布局添加到ContentView区域 ``` - 在`Activity.onCreate()`中调用`setContentView()`时: 1. 创建PhoneWindow(若未创建) 2. 初始化DecorView作为窗口根容器 3. 将用户布局注入DecorView的内容区(ID:`android.R.id.content`)[^1] - **关键特性**:此时DecorView已存在内存中,但尚未附加到窗口系统 #### 2. **onStop生命周期中的窗口处理** 当Activity进入`onStop()`状态时: ```java // ActivityThread.java void handleStopActivity(IBinder token, ...) { ActivityClientRecord r = getActivity(token); // 1. 回调Activity.onStop() r.activity.performStop(); // 2. 窗口可见性处理 if (r.window != null) { // 关键操作:通知WindowManager移除视图 r.windowManager.removeViewImmediate(r.window.getDecorView()); } } ``` - **窗口移除触发点**:`WindowManager.removeViewImmediate()`调用后: - 断开DecorView与ViewRootImpl的关联 - 通知SurfaceFlinger释放窗口的Surface - **视觉表现**:此时DecorView从屏幕消失,但对象仍在内存中[^3] #### 3. **DecorView与onStop的关键关联** | 生命周期阶段 | DecorView状态 | 系统操作 | |--------------|-------------------------------|--------------------------------------------------------------------------| | **onCreate** | 创建但未附加 | 初始化DecorView结构,加载用户布局 | | **onStart** | 附加到窗口但可能不可见 | 通过ViewRootImpl触发measure/layout/draw流程 | | **onResume** | 完全可见 | Choreographer提交帧到SurfaceFlinger渲染 | | **onStop** | 从窗口分离 | 1. 移除ViewRootImpl关联<br>2. 销毁窗口Surface<br>3. 停止事件分发绘制 | #### 4. **onStop后的特殊场景处理** - **配置变更(如旋转屏幕)**: ```java // ActivityThread.java void handleRelaunchActivity(...) { if (r.stopped) { // 若在onStop状态 // 重新创建DecorView窗口 handleLaunchActivity(r, null, "relaunch"); } } ``` 系统会重建DecorView并重新走完整附加流程 - **内存回收机制**: $$ \text{回收优先级} = \begin{cases} \text{onStop状态Activity} > \text{后台Service} \\ \text{无关联DecorView} > \text{可见窗口} \end{cases} $$ 处于onStopActivity其DecorView会优先被回收[^2] #### 5. **设计原理分析** 1. **资源隔离**:onStop时移除DecorView可立即释放GPU资源(如Texture) 2. **事件安全**:防止不可见窗口接收触摸事件 3. **渲染优化**:避免不可见窗口参与VSYNC合成流程 4. **快速恢复**:保留DecorView对象内存结构,加速onRestart时的视图恢复 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值