【发布时间】:2022-04-02 14:31:00
【问题描述】:
简单来说,我有一个 recyclerView,它的 viewHolders 持有 MediaPlayer 实例。当用户关闭该活动时,我想释放 MediaPlayer 实例获取的资源。但与 onCreateViewHolder 不同的是,我找不到任何 onDestroyViewHolder 方法。我的 viewHolder 实现如下所示:
class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val mMediaPlayer: MediaPlayer? = null
internal fun onBind(model: Model) {
if(model.contentType == "Audio") {
mMediaPlayer = MediaPlayer()
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mMediaPlayer.setOnCompletionListener(mCompletionListener);
mMediaPlayer.setDataSource(mContext, uri, null)
mMediaPlayer.prepareAsync()
// do other stuff
} else if(mMediaPlayer != null) {
mMediaPlayer.reset()
mMediaPlayer.release()
mMediaPlayer = null
}
}
}
我知道 Adapter 类有 onViewDetachedFromWindow 方法。但我不确定这是否适合这里。有人可以告诉我解决方案吗?
【问题讨论】:
-
“我有一个 recyclerView,它的 viewHolders 持有 mediaPlayer 实例”。这是组织代码的一种非常错误的方式。此类资源应由
Activity/Fragment持有。 -
@Onik,例如,在聊天应用程序(这是我正在尝试构建的)中,用户可以共享媒体。所以这将在聊天线程中显示和播放。如果无法在recyclerview 中播放音频,如何处理这种情况?这种情况有什么解决方法吗?
-
MediaPlayer 不是 UI 组件,因此不应存储在 UI 组件中。我不经常使用音频,但我的第一直觉是在 Fragment 中保留一个可用的 MediaPlayer 实例,创建一个用于设置新数据源并播放它的函数,然后从适配器中的 UI 组件调用该函数。
-
@Tenfour04,是的,我明白你的意思。甚至当我遇到这种情况时,我也有同感。但是,即使在同一视图中有多个音频,当我们按下播放按钮时,像 facebook/whatsapp 这样的 Messenger 应用程序也可以立即播放音频。如果它将 MediaPlayer 实例存储在 Fragment/Activity 中,那么它必须有一个 mediaPlayer 列表,每个都处于准备状态,具有视图中可见的所有不同音轨的 url。会是这样吗?这是一个更好的解决方案吗?还有其他想法吗?
-
这听起来像是一个潜在的解决方案,创建一个 MediaPlayerPool 类,这样您就可以独立控制一次预加载多少声音。你可以给它一个限制。因此,当视图出现在屏幕上时,他们会将声音 Uri 提交到 Pool,它可以使用下一个可用的 MediaPlayer 在其上调用
prepare(),如果它处于限制状态,则替换最旧的。您可能希望给它一个专用的处理程序来处理这些请求,以便它可以在后台关闭 UI 线程并保持prepare()和start()调用的顺序。
标签: android kotlin android-recyclerview android-mediaplayer android-lifecycle