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

RecyclerView中ComposeView调用setContent触发ViewTreeLifecycleOwner未找到异常

RecyclerView中使用ComposeView触发ViewTreeLifecycleOwnerNotFound崩溃的解决方案

我在RecyclerView的列表项中使用ComposeView,在RecyclerView.Adapter的onBindViewHolder方法里调用ComposeView.setContent(),但偶尔会触发以下崩溃:

Fatal Exception: java.lang.IllegalStateException: ViewTreeLifecycleOwner not found from android.widget.FrameLayout{cf04e92 VFE...C.. ......ID 0,599-1768,808 #7f0b05f5 app:id/root_container}
       at androidx.compose.ui.platform.WindowRecomposer_androidKt.createLifecycleAwareViewTreeRecomposer(WindowRecomposer_android.kt:244)
       at androidx.compose.ui.platform.WindowRecomposer_androidKt.access$createLifecycleAwareViewTreeRecomposer(WindowRecomposer_android.kt:1)
       at androidx.compose.ui.platform.WindowRecomposerFactory$Companion$LifecycleAware$1.createRecomposer(WindowRecomposerFactory.java:99)
       at androidx.compose.ui.platform.WindowRecomposerPolicy.createAndInstallWindowRecomposer$ui_release(WindowRecomposerPolicy.java:155)
       at androidx.compose.ui.platform.WindowRecomposer_androidKt.getWindowRecomposer(WindowRecomposer_android.kt:230)
       at androidx.compose.ui.platform.AbstractComposeView.resolveParentCompositionContext(AbstractComposeView.java:244)
       at androidx.compose.ui.platform.AbstractComposeView.ensureCompositionCreated(AbstractComposeView.java:251)
       at androidx.compose.ui.platform.AbstractComposeView.createComposition(AbstractComposeView.java:196)
       at androidx.compose.ui.platform.ComposeView.setContent(ComposeView.java:426)
       at a.b.c.f.s.viewholders.S.bind(S.java:154)
       at a.b.c.f.f.RvAdapter.onBindViewHolder(ForYouRvAdapter.java:48)
       at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7337)
       at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6194)
       at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6460)
       at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6300)
       at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6296)
       at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2330)
       at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1631)
       at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1591)
       at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:668)
       at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4309)
       at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3686)
       at android.view.View.measure(View.java:27720)
       at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:811)
       at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.measure(BasicMeasure.java:466)
       at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.measureChildren(BasicMeasure.java:134)
       at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:278)
       at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:120)
       at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1594)
       at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1708)
       at android.view.View.measure(View.java:27720)
       at androidx.core.widget.NestedScrollView.measureChildWithMargins(NestedScrollView.java:1792)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
       at androidx.core.widget.NestedScrollView.onMeasure(NestedScrollView.java:627)
       at android.view.View.measure(View.java:27720)
       at androidx.swiperefreshlayout.widget.SwipeRefreshLayout.onMeasure(SwipeRefreshLayout.java:705)
       at android.view.View.measure(View.java:27720)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7352)
       at androidx.coordinatorlayout.widget.CoordinatorLayout.onMeasureChild(CoordinatorLayout.java:760)
       at androidx.coordinatorlayout.widget.CoordinatorLayout.onMeasure(CoordinatorLayout.java:833)
       at android.view.View.measure(View.java:27720)
       at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7352)
       at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
       at android.view.View.measure(View.java:27720)
       at androidx.recyclerview.widget.RecyclerView$LayoutManager.measureChildWithMargins(RecyclerView.java:9681)
       at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1657)
       at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1591)
       at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:668)
       at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4309)
       at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4012)
       at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4578)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at androidx.viewpager2.widget.ViewPager2.onLayout(ViewPager2.java:527)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1873)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1873)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at androidx.coordinatorlayout.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1213)
       at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:899)
       at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:919)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
       at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at androidx.recyclerview.widget.RecyclerView$LayoutManager.layoutDecoratedWithMargins(RecyclerView.java:9878)
       at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1689)
       at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1591)
       at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:668)
       at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4309)
       at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:4012)
       at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4578)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at androidx.viewpager2.widget.ViewPager2.onLayout(ViewPager2.java:527)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
       at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
       at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
       at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
       at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
       at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
       at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
       at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1829)
       at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1673)
       at android.widget.LinearLayout.onLayout(LinearLayout.java:1582)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
       at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
       at com.android.internal.policy.DecorView.onLayout(DecorView.java:1432)
       at android.view.View.layout(View.java:24969)
       at android.view.ViewGroup.layout(ViewGroup.java:6784)
       at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:4917)
       at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:4240)
       at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:3116)
       at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:10885)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1301)
       at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1309)
       at android.view.Choreographer.doCallbacks(Choreographer.java:923)
       at android.view.Choreographer.doFrame(Choreographer.java:852)
       at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1283)
       at android.os.Handler.handleCallback(Handler.java:942)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loopOnce(Looper.java:226)
       at android.os.Looper.loop(Looper.java:313)
       at android.app.ActivityThread.main(ActivityThread.java:8757)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)

当前使用的Compose版本为androidx.compose.ui:ui:1.1.1。


崩溃原因

这个错误是因为ComposeView调用setContent()时,无法从View树中找到ViewTreeLifecycleOwner。通常发生在以下场景:

  • ItemView还未完全挂载到Activity/Fragment的View树时就调用了setContent()
  • RecyclerView快速滑动导致ItemView被回收复用时,View树关联的LifecycleOwner暂时失效

解决方案

1. 在ViewHolder初始化时绑定LifecycleOwner

在ViewHolder的构造方法中,提前给ComposeView设置LifecycleOwner,避免在onBindViewHolder时才处理。可以通过ViewTree获取当前的LifecycleOwner:

class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    val composeView: ComposeView = itemView.findViewById(R.id.compose_view)

    init {
        // 从根View获取LifecycleOwner
        ViewTreeLifecycleOwner.get(itemView.rootView)?.let { lifecycleOwner ->
            composeView.setLifecycleOwner(lifecycleOwner)
        }
    }
}

2. 延迟调用setContent确保View已挂载

在onBindViewHolder中,通过View.post()延迟执行setContent(),确保ItemView已经被添加到View树中:

override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
    holder.composeView.post {
        holder.composeView.setContent {
            // 你的Compose UI内容
            Text(text = "列表项 $position")
        }
    }
}

3. 升级Compose版本

Compose 1.1.1存在部分混合View系统的兼容性问题,升级到1.2.0及以上版本可以修复此类问题。修改gradle依赖:

implementation 'androidx.compose.ui:ui:1.2.0'
implementation 'androidx.compose.material:material:1.2.0'
// 同步升级其他相关Compose依赖,比如ui-tooling等

4. 替换为Compose原生LazyColumn(推荐)

如果项目架构允许,直接使用Compose原生的LazyColumn实现列表,彻底避免View系统和Compose的混合兼容性问题:

LazyColumn {
    items(yourDataList) { item ->
        // 列表项Compose UI
        Text(text = item.title)
    }
}

内容的提问来源于stack exchange,提问作者Arka Prava Basu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 09:57:03