You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android PictureInPicture模式Activity销毁重建及Fragment UI不显示问题

问题原因分析

1. 点击画中画X按钮触发Activity销毁重建的原因

  • 配置变更声明不全:画中画切换会触发屏幕方向、最小屏幕尺寸、UI模式等配置变更,你的Manifest中configChanges没有声明这三类变更,系统默认会销毁重建Activity来适配配置变化,从你进入画中画时的日志就能看到已经发生了一次重建,点击关闭按钮时的配置变更会再次触发该逻辑。
  • Activity启动模式和任务栈配置冲突:你给RoomActivity设置了singleTask启动模式、独立的taskAffinity以及excludeFromRecents=true,点击画中画关闭按钮时系统默认会finish当前Activity实例,但前台服务还在运行的状态下,系统检测到该任务栈没有可回退的页面,会触发Activity自动重建来留存任务栈。
  • 旧版Fragment标签的问题:你在布局中使用了已经不推荐的<fragment>标签来承载NavHostFragment,该标签在宿主Activity重建时会自动重新创建内部的Fragment实例,不会复用原有状态,加重了重建问题。

2. 通知打开后UI不显示的原因

点击X按钮后Activity异常重建时,Fragment的状态恢复出现异常,后续通过通知启动已经处于后台的Activity时,系统直接复用了异常状态的Fragment实例,没有触发onViewCreated生命周期,导致该方法中注册的观察者没有生效,UI无法更新。


解决方案

步骤1:补全configChanges配置,避免配置变更触发重建

在Manifest的RoomActivity的configChanges属性中添加画中画相关的配置变更声明:

android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|screenSize|fontScale|orientation|smallestScreenSize|uiMode"

添加后画中画切换带来的配置变更会由Activity自行处理,不会触发系统销毁重建逻辑。

步骤2:拦截画中画关闭事件,主动结束Activity避免异常重建

在RoomActivity中重写画中画模式变化和关闭请求的回调,点击关闭按钮时主动结束Activity,阻止系统自动重建:

override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) {
    super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
    // 退出画中画且没有前台展示需求时,直接关闭Activity
    if (!isInPictureInPictureMode) {
        finish()
    }
}

// Android 12及以上专门处理画中画关闭按钮点击
@RequiresApi(Build.VERSION_CODES.S)
override fun onCloseRequested() {
    super.onCloseRequested()
    finish()
}

步骤3:替换Fragment容器为官方推荐实现

把room_activity.xml中的<fragment>标签替换为FragmentContainerView,优化Fragment状态恢复逻辑:

<androidx.fragment.app.FragmentContainerView
    android:id="@+id/roomHostFragment"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:defaultNavHost="true"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:navGraph="@navigation/room_nav_graph" />

步骤4:调整PendingIntent配置,保证Activity启动状态正确

修改PendingIntent的Flag,匹配singleTask启动模式,同时保证参数可以正常更新:

private fun getPendingIntent(bundle: Bundle): PendingIntent =
    Intent(this@WebRtcVideoService, RoomActivity::class.java).let {
        it.putExtras(bundle)
        it.flags = Intent.FLAG_ACTIVITY_REORDER_TO_FRONT or Intent.FLAG_ACTIVITY_SINGLE_TOP
        val flag = when {
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> PendingIntent.FLAG_UPDATE_CURRENT
            else -> PendingIntent.FLAG_UPDATE_CURRENT
        }
        PendingIntent.getActivity(this@WebRtcVideoService, 0, it, flag)
    }

步骤5:优化观察者注册逻辑,兼容场景边缘case

将Fragment的观察者注册逻辑绑定到视图生命周期,就算Fragment复用也能正常收到回调:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    lifecycleScope.launch {
        repeatOnLifecycle(Lifecycle.State.STARTED) {
            viewModel.uiState.collect { uiState ->
                // 处理UI更新逻辑
            }
        }
    }
}

内容的提问来源于stack exchange,提问作者james04

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 07:36:07