Mobile Development 11 min read

Embedding Jetpack Compose in RecyclerView with ComposeView and Dispose Strategies

This article explains how to embed Jetpack Compose within an existing RecyclerView using ComposeView, examines the default DisposeOnDetachedFromWindow strategy, its impact on view recycling, and presents alternative composition strategies such as DisposeOnViewTreeLifecycleDestroyed and the newer pooling-aware strategy to improve performance.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Embedding Jetpack Compose in RecyclerView with ComposeView and Dispose Strategies

Background & Author's Note: The author introduces the growing popularity of Jetpack Compose and the desire to migrate existing View‑based projects to Compose using ComposeView , while warning about hidden performance costs.

Integrating Compose into the Existing View System: In a pure Compose project setContent { … } replaces setContentView . When adding Compose to a traditional View hierarchy, ComponentActivity.setContent creates a ComposeView and inserts it into android.R.id.content . The author demonstrates a simple activity that inflates a layout containing a RecyclerView and then creates a ComposeView for each item in the adapter.

class CustomActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_custom)
        val recyclerView = findViewById
(R.id.recyclerView)
        recyclerView.adapter = MyRecyclerViewAdapter()
        recyclerView.layoutManager = LinearLayoutManager(this)
    }
}

class MyRecyclerViewAdapter : RecyclerView.Adapter
() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyComposeViewHolder {
        val view = ComposeView(parent.context)
        return MyComposeViewHolder(view)
    }
    override fun onBindViewHolder(holder: MyComposeViewHolder, position: Int) {
        holder.composeView.setContent {
            Text(text = "test $position", modifier = Modifier.size(200.dp).padding(20.dp), textAlign = TextAlign.Center)
        }
    }
    override fun getItemCount() = 200
}

class MyComposeViewHolder(val composeView: ComposeView) : RecyclerView.ViewHolder(composeView)

Exploring Compose: The article briefly mentions Compose’s recomposition process and focuses on when a composition is disposed. The default strategy in Compose 1.1.1 is ViewCompositionStrategy.DisposeOnDetachedFromWindow , which adds an OnAttachStateChangeListener that calls view.disposeComposition() when the view is detached.

private var disposeViewCompositionStrategy: (() -> Unit)? =
    ViewCompositionStrategy.DisposeOnDetachedFromWindow.installFor(this)

The disposal implementation clears the composition, removes slots, and notifies the composer.

fun disposeComposition() {
    composition?.dispose()
    composition = null
    requestLayout()
}

Conflict with RecyclerView: Because RecyclerView recycles its ViewHolders, a ComposeView that has been disposed would no longer participate in recomposition. However, the setContent method recreates the composition if it is null, so recycled holders still work correctly.

fun setContent(content: @Composable () -> Unit) {
    shouldCreateCompositionOnAttachedToWindow = true
    this.content.value = content
    if (isAttachedToWindow) {
        createComposition()
    }
}

Other Dispose Strategies: The author introduces DisposeOnViewTreeLifecycleDestroyed , which disposes the composition only when the associated lifecycle reaches ON_DESTROY . This is set in the ViewHolder’s init block.

class MyComposeViewHolder(val composeView: ComposeView) : RecyclerView.ViewHolder(composeView) {
    init {
        composeView.setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
    }
}

Extension – New Default Strategy: Starting with Compose 1.3.0‑alpha02, the default strategy became DisposeOnDetachedFromWindowOrReleasedFromPool , which also checks view.isWithinPoolingContainer to avoid disposing views that are being pooled by RecyclerView. This reduces the hidden performance overhead when using Compose inside recyclable containers.

Conclusion: Compose offers significant architectural and performance benefits over the traditional View system, but developers must understand composition disposal strategies, especially when integrating with RecyclerView, to avoid unnecessary memory churn. The article encourages developers to adopt Compose and experiment with the newer pooling‑aware strategy.

performanceAndroidRecyclerViewComposeComposeViewDisposeStrategy
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.