Using Exoplayer in LazyColumn

I have been playing around with Compose
and recently implemented video playback in a list. While there are tons of great examples on
how to do it with a RecyclerView
, I couldn’t find any for Compose
.
So in this article, I will describe how I went about doing the same in Compose
. This article assumes you have some familiarity with Compose
and ExoPlayer
.
Let’s get started then — this is what we will be building.
Thinking it through 🧐
Before jumping into the code, let’s think about the scenarios we’ll be dealing with:
* A single video item is visible
* Multiple video items are visible
In a case of a single item, it’s pretty straightforward — we start the video playback as soon as the item is visible on the screen. In the case of multiple videos, however, we want to play the video which is closest to the center of the screen.
We also want to use a single ExoPlayer
instance instead of creating a new one for each video.
With that in mind, let’s dive into the code 🤿
Detecting the currently playing item 🔍
There’s a lot going on in the code so let’s go through it bit by bit. Firstly, we will be providing a listState
to the LazyColumn
as we will be using it to access the currently visible tweets. Moving onto the method determineCurrentlyPlayingItem
, we first check if any of the visible tweets have a video or gif in them. If we only find one such tweet, then we simply return that to be played. Else, we sort the column items by their distance from the center of the column and return the first item from that list.
Instantiating ExoPlayer 📺
Next up, we need to maintain an instance of ExoPlayer
and update it to play the currentlyPlayingItem
determined in the previous step. We will use remember
to maintain an instance of SimpleExoPlayer
for the lifetime of the screen.
For video playback, we will pass the currentlyPlayingItem
to the following method which will update the media source of the player.
However, if the tweet
is null
, we stop the playback so that any off-screen video isn’t playing anymore.
While it might seem like we are done, there is little thing we have forgotten about.

Just because we are in Compose
-land doesn’t mean we get to ignore the Android lifecycle. We will need to pause/resume the playback based on the lifecycle state as well as dispose of the ExoPlayer
instance when the lifecycle is destroyed.
Thankfully, Compose
provides a handy DisposableEffect
which allows you to perform cleanup whenever the key changes. We will use a lifecycleOwner
as the key.
This code is pretty self-explanatory — we just update the player
for various lifecycle events.
Playing the video ▶️
Last but not the least, we need to use the ExoPlayer
instance we created to actually play the video. Since there is no PlayerView
Composable yet, we will leverage Compose
interoperability and use AndroidView
instead.
Fin 👋🏾
Well, that’s about it. I was pleasantly surprised by how simple the Compose
implementation is as compared to its View
based counterpart as we don’t have to deal with the recycling of views.
Feel free to hit me up at @SHKM9 if you have any further questions or thoughts!