本文主要记录一些零碎的东西
使用IjkMediaPlayer 播放音乐时,快速点击切换播放的音乐,会出各种问题,本文给出一个修复方案,仅仅个人测试OK。
ijkplayer地址:https://github.com/Bilibili/ijkplayer
看看效果,不卡UI线程
解决思路:
问题:IjkMediaPlayer reset() 耗时,release() 在音频未加载完时,也是耗时操作
解决:使用两个队列,一个存放可以使用的IjkMediaPlayer,一个存放待 释放的IjkMediaPlayer,每次调用findAvailableMediaPlayer()都可取出一个可使用的播放器
待释放播放器在线程里 reset。
使用:
findAvailableMediaPlayer();
mMediaPlayer.setDataSource(url);
mMediaPlayer.prepareAsync();
关键方法:
private final static int MEDIA_PLAYER_NUM = 4;
private ExecutorService mExecutorService = Executors.newScheduledThreadPool(MEDIA_PLAYER_NUM);
private Queue<IjkMediaPlayer> mMediaPlayerQueue = new ArrayDeque<>();
private Queue<IjkMediaPlayer> mRecycleQueue = new ArrayDeque<>();
private IjkMediaPlayer mMediaPlayer;
private final Object mAvailableLocker = new Object();
/**
* create a new player and release current
* mMediaPlayer.reset(); cost too much time
* release() 在音频未加载完时,也是耗时操作
* 但是用户快速点击切换播放音乐,有问题
*
* 没有到限制播放器数量,直接新建
* 存在 可用队列 为空 的情况,即所有的 player 都在 reset ,此时直接新建
*
*/
private void findAvailableMediaPlayer() {
try {
if (currentPlayerNumLegal() || mMediaPlayerQueue.isEmpty()) {
D.i("create a new media player available size: " + mMediaPlayerQueue.size() + " recycle size: " + mRecycleQueue.size());
IjkMediaPlayer mediaPlayer = new IjkMediaPlayer();
mediaPlayer.setLooping(true);
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnPreparedListener(mPreparedListener);
mediaPlayer.setOnCompletionListener(mCompletionListener);
queueAvailableMediaPlayer(mediaPlayer);
}
if (mMediaPlayer != null) {
// 加入回收队列,待处理 释放
synchronized (mAvailableLocker) {
mRecycleQueue.add(mMediaPlayer);
}
}
// 此处 mMediaPlayer not null
D.i("availble media player size: " + mMediaPlayerQueue.size());
synchronized (mAvailableLocker) {
mMediaPlayer = mMediaPlayerQueue.poll();
}
if(mRecycleQueue.size() > 0) {
mExecutorService.execute(new Runnable() {
@Override
public void run() {
IjkMediaPlayer player;
synchronized (mAvailableLocker) {
player = mRecycleQueue.poll();
}
D.i("media player reset... ");
player.reset();
D.i("media player reset done... ");
queueAvailableMediaPlayer(player);
}
});
}
} catch (Exception e) {
D.e("media player error: " + e.getMessage());
}
}
private boolean currentPlayerNumLegal(){
synchronized (mAvailableLocker) {
return MEDIA_PLAYER_NUM > mMediaPlayerQueue.size() + mRecycleQueue.size();
}
}
private void queueAvailableMediaPlayer(IjkMediaPlayer player){
synchronized (mAvailableLocker) {
mMediaPlayerQueue.add(player);
D.i("media player size: " + mMediaPlayerQueue.size());
}
}
private IMediaPlayer.OnPreparedListener mPreparedListener =
new IMediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(IMediaPlayer mp) {
D.i("media player prepared ...");
mp.start();
}
};
private IMediaPlayer.OnCompletionListener mCompletionListener =
new IMediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(IMediaPlayer mp) {
D.i("media player completed ...");
}
};