Playlists
Playlist
s are reactive lists of videos that can be played and observed efficiently, with built-in
support for pagination, caching and preloading. This is the recommended way of fetching and
playing videos through our player.
As with querying videos, the start point is the video store (VideoKit.videos()
).
Also, to fetch playlist you will need a valid session or the call will return an error.
Inspecting playlists
Every playlist holds a list of videos in memory. At first, this list represent the first "page" of
results that were retrieved from server. These videos can be retrieved with the operator function Playlist.get
:
val playlist: Playlist = ...
val size: Int = playlist.size
val firstVideo: Video? = playlist[0]
Pagination
If get
is called with an index bigger than playlist.size
, it will throw an exception.
If you need more videos than those available at the moment, you can request a new batch of results
by using Playlist.loadMore()
:
// Load next page
val nextPage: Call<Unit> = playlist.loadMore()
nextPage.onSuccess {
// Got new videos!
}
Coroutine users can use loadMoreSuspending()
too.
Note that if Playlist.loadMoreOnAccess
is true (default), the playlist will automatically load new
pages as you consume the playlist with get
, checking if you are getting close enough to the last
available video. This makes it easy to show a list of videos without worrying about dynamic contents.
In case you want to access a video without triggering the "load more" logic, you have two choices:
- set
playlist.loadMoreOnAccess
to false - access
playlist.videos
directly
Observing playlists
At any time, you can use Playlist.videos
and Playlist.flow
to retreive the current list of videos
and, in case of the flow, to observe changes in it.
val playlist: Playlist = ...
val videos: List<Video> = playlist.video // won't trigger pagination
val flow: Flow<List<Video>> = playlist.flow
In addition, granular updates can be received by registering a Playlist.Observer
. This is extremely useful when
videos are shown in a RecyclerView
, for example, so that you can call the appropriate notify*
methods whenever something changes.
val playlist: Playlist = ...
playlist.addObserver(object: Playlist.Observer {
override fun onVideoInserted(id: String, index: Int) { ... }
override fun onVideoRemoved(id: String, index: Int) { ... }
override fun onVideoChanged(id: String, index: Int) { ... }
override fun onVideoMoved(id: String, fromIndex: Int, toIndex: Int) { ... }
})
Obtain playlists
As with other APIs, we use objects to define the query parameters. All such objects for playlists
extend the PlaylistSpec
interface. We expose several types of specs, each one with different
configuration options.
Once you have the spec, just call getPlaylist
:
val videos: VideoStore = VideoKit.videos()
val playlist = videos.getPlaylist(spec)
A similar function called loadPlaylist
will act just like getPlaylist
, but will also ensure
that the first batch of videos is loaded from network (or local database) before returning a result.
Loading is of course asynchronous. Coroutine projects can use loadPlaylistSuspending()
as well.
By user
You can filter by user using UserPlaylistSpec
:
val spec = UserPlaylistSpec(userIdentity)
val spec = UserPlaylistSpec.builder(userIdentity) {
order(SortOrder.DESC)
pageSize(50)
}
By metadata and tags
You can filter by metadata and tags using FilteredPlaylistSpec
:
val spec = FilteredPlaylistSpec(tags = tags, metadata = metadata)
val spec = FilteredPlaylistSpec.builder {
tags("tag1", "tag2")
metadata("key", "value")
order(SortOrder.DESC)
pageSize(50)
}
Custom playlists
You can create a playlist with custom videos using CustomPlaylistSpec
:
val spec = CustomPlaylistSpec(name = "MyVideos", ids = listOf("videoId1", "videoId2"))
This is a special type of playlist which can be controlled by the user. As you can imagine,
the playlist is mutable. You can use add
, remove
, set
functions to mutate the set of desired ids and missing videos will be loaded accordingly.
val playlist: CustomPlaylist = ...
// add video by ID. This is asynchronous
playlist.add(id = "videoId", position = 1).onSuccess {
}
Custom playlists have no built-in concept of pagination, so by default loadMore()
does nothing.
You can, however, pass a custom loader to playlist.loader
: in this case, the playlist will trigger
the loader whenever it thinks that a new page is needed, using the same triggering logic that is used
by other playlists.