管理和播放内容
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
本页介绍了如何使用预加载管理器来管理视频内容。通过使用预加载管理器,您可以为用户提供更好的体验;当用户从一个媒体项切换到另一个媒体项时,播放会更快开始,因为管理器已加载部分内容。
本页面涵盖以下主题:
将媒体内容添加到预加载管理器
您必须告知预加载管理器它将跟踪的每个媒体项。
例如,如果您的应用包含视频轮播界面,您需要将这些视频添加到预加载管理器。根据您的使用情形,您可以添加所有视频,也可以只添加当前正在播放的视频附近的所有视频。您也可以稍后向预加载管理器添加新项。
添加媒体项本身并不会导致预加载管理器开始加载内容。如需触发预加载,您需要使预加载管理器中的优先级失效。
val initialMediaItems = pullMediaItemsFromService(/* count= */ 20)
for (index in 0 until initialMediaItems.size) {
preloadManager.add(initialMediaItems.get(index), /* rankingData= */ index)
}
// items aren't actually loaded yet! need to call invalidate() after this
代码要点
- 此代码段展示了如何在创建预加载管理器后对其进行初始填充。您还可以调用
add()
将项添加到已填充的现有预加载管理器。
- 在此代码段中,
pullMediaItemsFromService()
是用于获取要播放的内容列表的应用逻辑。该代码会调用相应方法来提取最多 20 项的列表。
preloadManager
是在创建 DefaultPreloadManager
中创建的 DefaultPreloadManager
。该代码会调用相应管理器的 add()
方法来添加轮播界面中的每个项。
rankingData
是预加载管理器用于确定每个媒体项优先级的数值。对于 DefaultPreloadManager
,rankingData
是一个整数,表示相应媒体项在轮播界面中的位置。预加载管理器会根据每个内容与当前播放内容之间的距离来确定优先级。
使预加载管理器中的优先级失效
如需触发预加载管理器开始预加载内容,您需要调用 invalidate()
来告知预加载管理器,商品的优先级已过时。在以下情况下,您应执行此操作:
- 向预加载管理器添加新的媒体项或移除媒体项时。
如果您要添加或移除多个项,应先添加所有项,然后调用
invalidate()
。
- 当用户从一个媒体项切换到另一个媒体项时。在这种情况下,您应确保在调用
invalidate()
之前更新当前播放索引,如提取和播放内容中所述。
当您使预加载管理器失效时,它会调用您创建的 TargetPreloadStatusControl
来确定应从每个项中加载多少内容。然后,它会按优先级从高到低的顺序加载每个项的内容。
preloadManager.invalidate()
代码要点
- 调用
invalidate()
会触发预加载管理器重新评估其了解的每项媒体内容的优先级。因此,如果您要对预加载管理器进行大量更改,则应在调用 invalidate()
之前完成更改。
获取和播放媒体
当用户前进到新的媒体项时,您需要从预加载管理器中获取该媒体项。如果预加载管理器已加载任何内容,则内容播放速度会比您未使用预加载管理器时更快。如果预加载管理器尚未加载相应项中的内容,则内容会正常播放。
// When a media item is about to display on the screen
val mediaSource = preloadManager.getMediaSource(mediaItem)
if (mediaSource != null) {
player.setMediaSource(mediaSource)
} else {
// If mediaSource is null, that mediaItem hasn't been added to the preload manager
// yet. So, send it directly to the player when it's about to play
player.setMediaItem(mediaItem)
}
player.prepare()
// When the media item is displaying at the center of the screen
player.play()
preloadManager.setCurrentPlayingIndex(currentIndex)
// Need to call invalidate() to update the priorities
preloadManager.invalidate()
代码要点
player
是应用用于播放内容的 Media3 ExoPlayer
。您必须通过在用于创建预加载管理器的同一构建器上调用 DefaultPreloadManager.Builder.buildExoPlayer()
来创建该播放器。
- 当用户切换到新的媒体项时,应用会调用
getMediaSource()
以从预加载管理器获取媒体源。必须是您已添加到预加载管理器的 mediaItem
。即使预加载管理器尚未开始加载内容,也没关系;在这种情况下,它会返回一个不含预加载数据的 MediaSource
。例如,如果用户突然在轮播界面中跳到很远的位置,就可能会发生这种情况。
- 在用户播放新的媒体项后,请调用
setCurrentPlayingIndex
来告知预加载管理器新项在轮播界面中的位置。预加载管理器需要该信息来确定下一项的加载优先级。更新当前索引后,调用 invalidate()
可让预加载管理器重新确定每个项目的优先级。
从预加载管理器中移除内容
为确保预加载管理器高效运行,您应移除预加载管理器不再需要跟踪的项。您还可以移除仍位于轮播界面中但距离用户当前位置较远的内容。例如,您可能会决定,如果某个商品与用户正在观看的内容相差超过 15 项,则无需预加载该商品。在这种情况下,您会在商品距离过远时将其移除。如果用户重新向已移除的内容移动,您可以随时重新添加这些内容。
preloadManager.remove(mediaItem)
代码要点
在不再需要预加载管理器时释放它
当您不再需要预加载管理器时,必须释放它以释放其资源。特别是,请务必在 activity 被销毁时释放它。
preloadManager.release()
preloadManager.release()
代码要点
- 释放对象后,您不得调用该对象的任何方法。
- 如果您需要创建另一个预加载管理器,请创建一个新的
DefaultPreloadManager.Builder
,并使用它来创建 DefaultPreloadManager
。请勿尝试重复使用旧的 build。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-09-11。
[null,null,["最后更新时间 (UTC):2025-09-11。"],[],[],null,["This page describes how to use a preload manager to manage video content. By\nusing a preload manager, you can give the user a better experience; when the\nuser switches from one media item to another, the playback starts faster because\nthe manager has already loaded some of the content.\n\nThis page covers the following topics:\n\n- [Add media items to the preload manager](#add-items)\n- [Invalidate the priorities in the preload manager](#invalidate)\n- [Fetch and play media](#fetch-play)\n- [Remove items from the preload manager](#remove)\n- [Release the preload manager when you're done with it](#release)\n\nAdd media items to the preload manager\n\nYou have to tell the preload manager about each media item it will be tracking.\nFor example, if your app has a carousel of videos, you'd add those videos to the\npreload manager. Depending on your use case, you might add all the videos, or\njust all the videos near the video that's currently playing. You can also add\nnew items to the preload manager later.\n\nAdding the media items does not, by itself, cause the preload manager to start\nloading the content. To trigger the preloading, you'll need to [invalidate the\npriorities in the preload manager](#invalidate).\n\n\n```kotlin\nval initialMediaItems = pullMediaItemsFromService(/* count= */ 20)\nfor (index in 0 until initialMediaItems.size) {\n preloadManager.add(initialMediaItems.get(index), /* rankingData= */ index)\n}\n// items aren't actually loaded yet! need to call invalidate() after this \nhttps://github.com/android/snippets/blob/9efabddf7d28b059560ab8e3d3e584fabe481501/misc/src/main/java/com/example/snippets/PreloadManagerKotlinSnippets.kt#L79-L83\n```\n\n\u003cbr /\u003e\n\nKey points about the code\n\n- This snippet shows how to initially populate the preload manager after you've created it. You can also call `add()` to add items to an existing, populated preload manager.\n- In this snippet, `pullMediaItemsFromService()` is the app's logic to fetch the list of content to play. The code calls that method to fetch a list of up to 20 items.\n- `preloadManager` is the `DefaultPreloadManager` created in [Create a\n `DefaultPreloadManager`](/media/media3/exoplayer/preloading-media/preloadmanager/create). The code calls that manager's `add()` method to add each item in the carousel.\n- `rankingData` is a value the preload manager uses to determine the priority of each media item. For `DefaultPreloadManager`, `rankingData` is an integer representing the item's position in the carousel. The preload manager determines the priority by how far each item is from the item that's currently playing.\n\nInvalidate the priorities in the preload manager\n\nTo trigger the preload manager to start preloading content, you need to call\n`invalidate()` to tell the preload manager that the priorities of items are out\nof date. You should do this in the following situations:\n\n- When you add new media items to the preload manager, or remove media items. If you're adding or removing several items, you should add all of them, *then* call `invalidate()`.\n- When the user switches from one media item to another. In this case, you should make sure to update the current playing index *before* you call `invalidate()`, as described in [Fetch and play content](#fetch-play).\n\nWhen you invalidate the preload manager, it calls the\n[`TargetPreloadStatusControl` you created](/media/media3/exoplayer/preloading-media/preloadmanager/create#create-tpsc) to find out how much content\nit should load from each item. It then loads the content for each item in the\norder of their priority from high to low.\n\n\n```kotlin\npreloadManager.invalidate()https://github.com/android/snippets/blob/9efabddf7d28b059560ab8e3d3e584fabe481501/misc/src/main/java/com/example/snippets/PreloadManagerKotlinSnippets.kt#L87-L87\n```\n\n\u003cbr /\u003e\n\nKey points about the code\n\n- Calling `invalidate()` triggers the preload manager to re-evaluate the priority of each media item it knows about. For this reason, if you're making a lot of changes to the preload manager, you should finish making the changes before you call `invalidate()`.\n\nFetch and play media\n\nWhen the user advances to a new media item, you need to get the media item from\nthe preload manager. If the preload manager has loaded any of the content, the\ncontent plays faster than it would have if you hadn't used the preload manager.\nIf the preload manager hasn't loaded content from that item yet, the content\nplays normally.\n\n\n```kotlin\n// When a media item is about to display on the screen\nval mediaSource = preloadManager.getMediaSource(mediaItem)\nif (mediaSource != null) {\n player.setMediaSource(mediaSource)\n} else {\n // If mediaSource is null, that mediaItem hasn't been added to the preload manager\n // yet. So, send it directly to the player when it's about to play\n player.setMediaItem(mediaItem)\n}\nplayer.prepare()\n\n// When the media item is displaying at the center of the screen\nplayer.play()\npreloadManager.setCurrentPlayingIndex(currentIndex)\n\n// Need to call invalidate() to update the priorities\npreloadManager.invalidate()https://github.com/android/snippets/blob/9efabddf7d28b059560ab8e3d3e584fabe481501/misc/src/main/java/com/example/snippets/PreloadManagerKotlinSnippets.kt#L99-L115\n```\n\n\u003cbr /\u003e\n\nKey points about the code\n\n- `player` is the Media3 `ExoPlayer` the app is using to play the content. You must create that player by calling [`DefaultPreloadManager.Builder.buildExoPlayer()`](/reference/androidx/media3/exoplayer/source/preload/DefaultPreloadManager.Builder#buildExoPlayer()) on the same builder you used to create the preload manager.\n- When the user switches to a new media item, the app calls `getMediaSource()` to get the media source from the preload manager. This must be a `mediaItem` you have [already added to the preload manager](#add-items). It's okay if the preload manager hasn't already started loading the content; in that case, it returns a `MediaSource` that doesn't have preloaded data. For example, this might happen if the user suddenly jumps far ahead in the carousel.\n- After the user plays the new media item, call `setCurrentPlayingIndex` to tell the preload manager where in the carousel the new item is. The preload manager needs that information to prioritize loading the next item. After you update the current index, [call `invalidate()`](#invalidate) to make the preload manager redetermine the priority for each item.\n\nRemove items from the preload manager\n\nTo keep the preload manager efficient, you should remove items the preload\nmanager no longer needs to track. You might also remove items that are still in\nthe carousel, but are far away from the user's current position. For example,\nyou might decide that if an item is more than 15 items away from what the user\nis watching, it doesn't need to be preloaded. In that case, you'd remove items\nwhen they got that far away. If the user moves back towards those removed items,\nyou can always [add them back](#add-items).\n\n\n```kotlin\npreloadManager.remove(mediaItem)https://github.com/android/snippets/blob/9efabddf7d28b059560ab8e3d3e584fabe481501/misc/src/main/java/com/example/snippets/PreloadManagerKotlinSnippets.kt#L122-L122\n```\n\n\u003cbr /\u003e\n\nKey points about the code\n\n- If you want to remove *all* the items from the preload manager, you can call [`reset()`](/reference/androidx/media3/exoplayer/source/preload/BasePreloadManager#reset()) instead of `remove()`. This approach is useful if you need to change all the items in your carousel. In that case, after you remove the items, you'll need to [add new items to the preload manager](#add-items) then [invalidate the priorities in the preload manager](#invalidate).\n\nRelease the preload manager when you're done with it\n\nWhen you no longer need the preload manager, you must release it to free up its\nresources. In particular, make sure to release it when your activity is\ndestroyed.\n\n\n```kotlin\npreloadManager.release()https://github.com/android/snippets/blob/9efabddf7d28b059560ab8e3d3e584fabe481501/misc/src/main/java/com/example/snippets/PreloadManagerKotlinSnippets.kt#L129-L129\n```\n\n\u003cbr /\u003e\n\n preloadManager.release()\n\nKey points about the code\n\n- You *must not* call any of the object's methods after you release it.\n- If you need to create another preload manager, create a new `DefaultPreloadManager.Builder` and use it to create the `DefaultPreloadManager`. Don't try to reuse the old builder."]]