Media Player反复加载媒体



我正在制作一个聊天应用程序,我已经实现了发送音频消息的功能。但在这里我发现了一件我不希望发生的事。它是,每当我的适配器更新,媒体播放器开始再次加载。这样就会出现一个问题,如果有人正在听音频,而另一端的用户发送了一条消息,媒体播放器就会停止并重新加载。这是我的适配器的代码。

final MediaPlayer mediaPlayer;
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
handler = new Handler();
try {
mediaPlayer.setOnCompletionListener(mediaPlayer1 -> {
mediaPlayer1.stop();
binding.audioSeekbar.setProgress(0);
});
if (mediaPlayer.isPlaying()){
mediaPlayer.stop();
mediaPlayer.release();
}
mediaPlayer.setDataSource(finalUrlToLoad[1]);
mediaPlayer.setVolume(1f, 1f);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(mediaPlayer1 -> {
int totalDuration = mediaPlayer1.getDuration();
binding.totalDurationAudio.setText(createTimeLabel(totalDuration));
binding.loadingAudio.setVisibility(GONE);
binding.playPauseAudio.setVisibility(VISIBLE);
});
} catch (IOException e) {e.printStackTrace();}
binding.playPauseAudio.setOnClickListener(view -> {
if (mediaPlayer.isPlaying()){
handler.removeCallbacks(runnable);
mediaPlayer.pause();
binding.playPauseAudio.setImageResource(R.drawable.pause_to_play);
Drawable drawable = binding.playPauseAudio.getDrawable();
if( drawable instanceof AnimatedVectorDrawable) {
AnimatedVectorDrawable animation = (AnimatedVectorDrawable) drawable;
animation.start();
}
}else {
mediaPlayer.seekTo(binding.audioSeekbar.getProgress());
mediaPlayer.start();
handler.post(runnable);
binding.playPauseAudio.setImageResource(R.drawable.play_to_pause);
Drawable drawable = binding.playPauseAudio.getDrawable();
if( drawable instanceof AnimatedVectorDrawable) {
AnimatedVectorDrawable animation = (AnimatedVectorDrawable) drawable;
animation.start();
}
}
});
runnable = () -> {
int totalTime = mediaPlayer.getDuration();
binding.audioSeekbar.setMax(totalTime);
int currentPosition = mediaPlayer.getCurrentPosition();
binding.audioSeekbar.setProgress(currentPosition);
binding.totalDurationAudio.setText(createTimeLabel(totalTime));
Log.d("time", String.valueOf(currentPosition));
handler.postDelayed(runnable,1000);
};
binding.audioSeekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (b){
mediaPlayer.seekTo(i);
seekBar.setProgress(i);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
mediaPlayer.setOnBufferingUpdateListener((mediaPlayer1, i) -> binding.audioSeekbar.setSecondaryProgress(i));

这里finalurltload[1]是音频的url。

现在我需要做些什么来防止一次又一次地加载它

谁回答这个问题我将非常感激。

谢谢😊。

很难从这段代码中看出,但我认为这是在你的onBind事件中设置的?如果是这样,那么这意味着每次RecyclerView创建一个新的holder并绑定它时,相关的媒体将被准备和加载,无论最后一个被onBind调用的holder是谁,都将"赢"。(这是MediaPlayer将加载的内容)。因为默认情况下,RecyclerView通常会在前面创建多个holder,所以你会看到你的MediaPlayer被"加载"了。很多次了。

你可能只是不想在onBind中初始化每个音频消息。相反,只需使用onBind事件将状态变量(持续时间,进度等)初始化为一些默认值,隐藏它们并绑定特定的音频Uri。然后当用户采取一些动作,比如轻敲支架时,在初始化发生时取消隐藏不确定的进度条,并在onPrepared()事件中取消隐藏状态信息(持续时间,进度,搜索栏等),最后隐藏不确定的进度条并开始音频。

我假设你也发送声音文件作为你的消息应用程序的一部分(即不存储它在网络的某个地方在一个中心位置?),这个文件被存储在一个应用程序特定的存储位置?如果是这样,您就不需要为持久化该URI的权限而担心,但是如果不是这种情况,您就需要。

  1. 首先将媒体播放器代码提取到单个类中,如AudioManager
  2. 添加一些方法,如setMediaUpdateListener,为seek持续时间设置回调。和togglePlayPause播放或暂停音频。
  3. 在播放视频时向音频管理器传递消息id或任何唯一标识符。

在适配器类的onBind方法。

  1. 首先比较id和播放id是相同的AudioManager.getInstance().isPlaying(messageId);

  2. 如果是,则设置seekUpdatelistner为音频管理器类。同时根据audiomemanager . isplaying()方法更新播放/暂停图标。

3。如果用户播放其他消息,请单击播放按钮。调用audiomemanager .play(message)方法。其中,我们释放之前的消息并播放新的消息。

  1. 如果当前消息未播放,则重置非播放状态视图

  2. 如果自动播放是启用的,那么你需要检查audioManager是否空闲,那么只有你可以播放最后一条消息,否则会被忽略。

就像一个为你管理音频并存储所有状态的类。

class AudioManager {
public static AudioManager instance;
final MediaPlayer mediaPlayer;
private AudioListener audioListener;
private Uri currentPlaying;
public AudioManager getInstance() {
if (instance == null) {
instance = new AudioManager();
}
}

public void play(Uri dataUri) {
if (mediaPlayer != null && currentPlaying == null || currentPlaying.equals(dataUri)) {
if (!mediaPlayer.isPlaying) {
mediaPlayer.play();
}
return;
} else if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
}
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
handler = new Handler();
try {
mediaPlayer.setOnCompletionListener(mediaPlayer1 -> {
mediaPlayer1.stop();
sendProgress(0);
});
if (mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
}
mediaPlayer.setDataSource(dataUri;
mediaPlayer.setVolume(1f, 1f);
mediaPlayer.prepareAsync();
mediaPlayer.setOnPreparedListener(mediaPlayer1 -> {
int totalDuration = mediaPlayer1.getDuration();
sendTotalDuration(totalDuration);
});
} catch (IOException e) {
e.printStackTrace();
}
}
public void pause() {
// update the pause code.
}
public void sendProgress(int progress) {
if (audioListener != null) {
audioListener.onProgress(progress);
}
}
public void sendTotalDuration(int duration) {
if (audioListener != null) {
audioListener.onTotalDuraration(duration);
}
}
public void AudioListener(AudioListener audioListener) {
this.audioListener = audioListener;
}
public interface AudioListener {
void onProgress(int progress);
void onTotalDuraration(int duration);
void onAudioPlayed();
void onAudioPaused():
}

}

最新更新