当前位置: 首页 > 知识库问答 >
问题:

MediaPlayer从适配器调用片段中更新seekbar时跳过音频

董子航
2023-03-14

我有一个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在适配器中定义为全局变量。

共有2个答案

安奇
2023-03-14

您可能需要在片段中创建mmediplayer,然后将侦听器作为构造函数参数传递给适配器。一旦调用了监听器,就可以将mediaplayer参数传递给监听器,并在片段中执行其余的mMediaPlayer操作。通过这种方式,您还可以访问getActivity()上下文

您可以将这个侦听器从片段传递到适配器

public interface OnMediaPlayerInvoked {
void onSeekBarPosition(your params);
}

然后从适配器中调用这个监听器,并将参数传递给MediaPalyerInvoked上的监听器,以便其余的操作可以在片段中执行

满雨石
2023-03-14

我猜跳过和暂停是因为使用了太多的主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: 列表适配器