我有一个MediaPlayer,它包含在一个自定义的ViewHolder中,由一个片段运行的RecycleServiceAdapter创建。我正在尝试每秒更新seekbar,以显示MediaPlayer正在播放的音频的进度,使用以下问题的答案:
private Handler mHandler = new Handler();
//Make sure you update Seekbar on UI thread
MainActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
if(mMediaPlayer != null){
int mCurrentPosition = mMediaPlayer.getCurrentPosition() / 1000;
mSeekBar.setProgress(mCurrentPosition);
}
mHandler.postDelayed(this, 1000);
}
});
但是,由于我是从片段在适配器中运行它,而不是直接在活动中运行,所以我不能使用这一行:
MainActivity.this.runOnUiThread(new Runnable() {
因此,我用适配器的构造函数将getActivity()
从片段传递到RecycleServiceAdapter,并将其设置为全局变量parentActivity
然后,我创建了代码来更新RecycleServiceAdapter的onBindViewHolder()中的seekbar,如下所示:
final Handler mHandler = new Handler();
this.parentActivity.runOnUiThread(new Runnable(){
@Override
public void run(){
if (mMediaPlayer != null){
int mCurrentPosition = mMediaPlayer.getCurrentPosition();
myViewHolder.seekBar.setProgress(mCurrentPosition);
}
mHandler.postDelayed(this, 1000);
}
});
我的问题是,现在当我播放音频时,尽管seekbar更新正常,但音频会短暂暂停,或每秒“跳过”。这可能是什么原因造成的?我该如何修复它?
编辑:每个ViewHolder都有自己的SeekBar,mmediplayer
在适配器中定义为全局变量。
您可能需要在片段中创建mmediplayer
,然后将侦听器作为构造函数参数传递给适配器。一旦调用了监听器,就可以将mediaplayer参数传递给监听器,并在片段中执行其余的mMediaPlayer
操作。通过这种方式,您还可以访问getActivity()
上下文
您可以将这个侦听器从片段传递到适配器
public interface OnMediaPlayerInvoked {
void onSeekBarPosition(your params);
}
然后从适配器中调用这个监听器,并将参数传递给MediaPalyerInvoked上的监听器,以便其余的操作可以在片段中执行
我猜跳过和暂停是因为使用了太多的主thred,更重要的是有多个活动实例。如果你把它复制到你的回收商的每一个浏览者那里,就会发生这种情况。
事实上,这是一种非常糟糕的模式,任何时候都应该避免。
很难给你提供解决方案,因为你没有弄清楚你的应用程序到底是什么样子的(例如,每个视图持有者中都有seekbar等)。但假设这是“最坏”的情况,我建议您将另一个侦听器传递给适配器,适配器将侦听您的seekBar或ViewHolder(取决于您,实际上,对于扩展控制,这个接口可能会更大)。碎片会在其内部进行刷新。
class Adapter(... startPlayingListener: (SeekBar) -> Unit) {
fun onBindViewHolder() {
whateverButton.setOnClickListener {startPlayingListener.invoke(seekBar)}
}
}
class Fragment(...) {
fun bindAdapter() {
adapter = YourAdapter(..., this::onPlayerStart)
}
fun onPlayerStart(seekBar: SeekBar) {
this.parentActivity.runOnUiThread(
{
if (mMediaPlayer != null){
int mCurrentPosition = mMediaPlayer.getCurrentPosition();
seekBar.setProgress(mCurrentPosition);
}
mHandler.postDelayed(this, 1000);
}
}
}
编辑:
正如您所说,您的解决方案只有一个要播放的歌曲列表,每个项目都有自己的SeekBar。在这种情况下,我建议您创建一个代理类来处理播放音乐的逻辑,并仅将ViewHolder用作视图(在其他情况下,为MVP的Presenter层创建类)。下面我发布的代码或多或少地展示了这个想法。
public interface YourPlayerView() {
void updateSeekBar(int currentPosition);
}
public interface YourPlayerPresenter {
void startPlaying(YourPlayerView view, trackID or something)
void stopPlaying(YourPlayerView view, trackID or something)
}
class YourPlayer(...) implements YourPlayerPresenter {
private MediaPlayer;
@Override
public void startPlaying(YourPlayerView view, trackId or something) {
//start the track - possibly pass it as an argument of this method
//start your handler calling view.updateSeekBar(...)
}
}
public class ViewHolder(YourPlayerPresenter player) implements YourPlayerView {
void bind(...) {
buttonStart.setOnClickListener(player.startPlaying(this, trackId);
}
@Override
public void updateSeekBar(int currentPosition) {
mSeekBar.setProgress(currentPositition)
}
}
但问题是我想知道如何从类中的片段调用方法?这是我的代码 下面是在活动中工作但在片段中不工作的代码
我正在使用一个片段来查看一个RecyclerView。但我总是犯这个错误 E/RecyclerView:未附加适配器;跳过布局 我已经为我的recyclerview创建了一个适配器,但布局没有显示。php后端运行良好。谁能帮帮我。下面是我的片段和适配器代码 Tips.java TipAdapter.java
我的片段中的回收视图给我这个错误,但我无法弄清楚。关于这个问题有很多问题,但到目前为止,它们都没有解决我的问题。 这是我的片段中的一段代码:
给我的 我已经尝试了我找到的所有解决方案(设置一个空适配器,将代码移动到哪里,使用单独的线程),但无济于事。这应该适用于正常的活动,所以我想也许我做错了什么。
问题内容: 这个想法是我有一个列表视图,其中每个项目都是一个产品,当我单击该项目时,我需要从列表视图的适配器内部的单击中转到另一个片段。 我的适配器是: 您必须假设所有代码都在工作。 如何转到适配器内的产品Fragment? 问题答案: 为了解决这个问题,我要做的是: 在主类中,我将参数作为值,并通过开关在我感兴趣的main中设置了片段。
我正在尝试在片段中使用回收器视图,但我遇到一个问题,我的列表没有出现,我有这个错误: e/recycle view:未连接适配器;跳过布局 我检查了解决方案,显然问题出现在: > < li > < p > RecyclerView在适配器后初始化 绑定和设置回收器在“创建”查看“而不是”创建“中查看 但我注意到了,我尝试了其他选择,我仍然面临着同样的问题。 这是我的片段代码: XML: 列表适配器