返回Fragment时AbstractComposeView自定义Compose视图不绘制
问题场景
在Fragment的XML布局中使用继承自AbstractComposeView的自定义Compose视图,该Fragment属于Jetpack Navigation导航图的管理范围。
问题现象
首次打开该Fragment时,Compose视图可以正常绘制显示,但按下返回键回到该Fragment时,Compose视图直接消失,仅首次进入时可正常渲染。
相关实现代码
class ProgressComposeView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : AbstractComposeView(context, attrs, defStyleAttr) { private var steps = mutableStateOf(0) private var currentStep: Int = 0 private var windowWidth: Int = 0 @Composable override fun Content() { ProgressView(steps.value, currentStep, windowWidth) } fun setData(steps: Int, currentStep: Int, windowWidth: Int) { this.steps.value = steps this.currentStep = currentStep this.windowWidth = windowWidth } } @Composable fun ProgressView(totalSteps: Int, currentStep: Int, windowWidth: Int) { // 具体业务布局逻辑 }
问题根因
AbstractComposeView默认会在视图从窗口分离(对应Fragment被压入返回栈、视图销毁的场景)时自动释放持有的Compose Composition实例,但在视图重新附着回窗口(对应从返回栈回到该Fragment的场景)时,不会自动重建Composition,导致视图没有可渲染的内容,直接显示空白。- 代码中
currentStep、windowWidth两个字段是普通基础类型,不属于Compose可观察状态,后续调用setData更新这两个值时,无法触发Compose重组,就算视图正常显示也不会同步最新数据。
修复方案
- 修改自定义
ProgressComposeView的实现,补全视图重附着时的Composition重建逻辑,同时将所有驱动UI的字段改为Compose可观察状态:
class ProgressComposeView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : AbstractComposeView(context, attrs, defStyleAttr) { // 所有参与UI渲染的字段都声明为可观察的MutableState private var steps by mutableStateOf(0) private var currentStep by mutableStateOf(0) private var windowWidth by mutableStateOf(0) @Composable override fun Content() { ProgressView(steps, currentStep, windowWidth) } fun setData(steps: Int, currentStep: Int, windowWidth: Int) { this.steps = steps this.currentStep = currentStep this.windowWidth = windowWidth } override fun onAttachedToWindow() { super.onAttachedToWindow() // 视图重新附着时,若Composition已被释放则主动重建 if (composition == null) { createComposition() } } }
- 在宿主Fragment的
onDestroyView生命周期中,主动调用该Compose视图的disposeComposition()方法释放资源,避免内存泄漏:
override fun onDestroyView() { binding.progressComposeView.disposeComposition() super.onDestroyView() }
注意:不要直接将
disposeCompositionWhenDetachedFromWindow属性设为false关闭自动释放逻辑,该配置会导致RecyclerView复用、临时视图detach等场景下Compose持有无效引用,提升内存泄漏风险。
内容的提问来源于stack exchange,提问作者Oussaki
相关产品推荐
相关产品推荐

