java - ExoPlayer - java.lang.IllegalStateException:向死线程上的处理程序发送消息
问题描述
我在 RecyclerView 中使用 SimpleExoPlayer,有时调用时出错
simplePlayer.setPlayWhenReady(true);
视频播放器保持空白,出现问题的时刻并不总是相同(我没有找到模拟这个的确切方法)
例外:
java.lang.IllegalStateException: Handler (android.os.Handler) {edbfbdd} sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:545)
at android.os.Handler.enqueueMessage(Handler.java:662)
at android.os.Handler.sendMessageAtTime(Handler.java:631)
at android.os.Handler.sendMessageDelayed(Handler.java:601)
at android.os.Handler.sendMessage(Handler.java:538)
at android.os.Message.sendToTarget(Message.java:418)
at com.google.android.exoplayer2.ExoPlayerImplInternal.setPlayWhenReady(ExoPlayerImplInternal.java:183)
at com.google.android.exoplayer2.ExoPlayerImpl.setPlayWhenReady(ExoPlayerImpl.java:245)
at com.google.android.exoplayer2.SimpleExoPlayer.updatePlayWhenReady(SimpleExoPlayer.java:1188)
at com.google.android.exoplayer2.SimpleExoPlayer.setPlayWhenReady(SimpleExoPlayer.java:896)
我的代码在自定义视图中运行(在回收器视图适配器中更新):
MyView h = this;
h.playerView = new PlayerView(getContext());
h.playerView.setVisibility(View.GONE);
h.postFrameLayout.addView(h.playerView, 0);
h.postFrameLayout.getLayoutParams().width = swidth;
h.postFrameLayout.getLayoutParams().height = (int) (swidth );
h.playerView.getLayoutParams().width = swidth;
h.playerView.getLayoutParams().height = (int) (swidth );
if (player != null){
player.release();
}
DefaultLoadControl loadControl = new DefaultLoadControl.Builder()
.setBufferDurationsMs(1100, 2000, 1000, 1000).createDefaultLoadControl();
final SimpleExoPlayer simplePlayer = ExoPlayerFactory.newSimpleInstance(getContext(), trackSelector, loadControl);
h.playerView.setUseController(false);
h.playerView.setResizeMode(AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH);
h.playerView.setPlayer(simplePlayer);
simplePlayer.addListener(new Player.EventListener() {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == Player.STATE_ENDED) {
h.videoPlay.setVisibility(View.VISIBLE);
h.postImage.setVisibility(View.VISIBLE);
simplePlayer.setPlayWhenReady(false);
simplePlayer.seekTo(0);
}
}
});
Uri uri = Uri.parse(videoUrl);
final MediaSource audioSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(uri);
simplePlayer.prepare(audioSource);
h.player = simplePlayer;
h.videoPlay.setVisibility(View.VISIBLE);
h.videoPlay.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
displayArticles(false, post.getPhotoItems(), h);
h.videoPlay.setVisibility(View.GONE);
h.postImage.setVisibility(View.GONE);
h.playerView.setVisibility(View.VISIBLE);
simplePlayer.setPlayWhenReady(true);
}
});
我在从窗口分离时释放播放器(当回收器视图在我的自定义视图上调用 onDetachedFromWindow() 时):
if (player != null) {
videoPlay.setVisibility(View.VISIBLE);
postImage.setVisibility(View.VISIBLE);
player.release();
player = null;
}
有没有办法避免这个问题或在播放器启动时重试?
解决方案
当我尝试使用..exoplayer2.ui.PlayerView类时,我遇到了同样的问题。..exoplayer2.ui.PlayerControlView没有问题。这是我的代码:
public static void setUp(Context context){
ExoPlayerTool.context = context;
player = new SimpleExoPlayer.Builder(context).build();
dataSourceFactory = new DefaultDataSourceFactory(context,
Util.getUserAgent(context, "SingerApp"));
}
public static void setSource(String link){
Uri uri = Uri.parse(link);
MediaSource videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
player.addListener(playerListener);
player.prepare(videoSource);
player.setPlayWhenReady(true);
}
我调用setup()
一次setSource()
函数,每次我想更改源时都调用函数。
当我想关闭音乐时,我打电话player.release();
并释放后setSource()
,在线给出同样的错误player.prepare(videoSource);
。
我能够通过在每次源更改时创建新的SimpleExoPlayer来解决这个问题。代码如下所示:
public static void setSource(String link){
Uri uri = Uri.parse(link);
MediaSource videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory).createMediaSource(uri);
player.release();
player = new SimpleExoPlayer.Builder(context).build();
player.addListener(playerListener);
player.prepare(videoSource);
player.setPlayWhenReady(true);
}
我不知道这个解决方案的优化程度如何,但总比不发布播放器要好。
推荐阅读
- node.js - Does Express access an app.get(/:params) if the user didn't type anything in the URL
- arrays - 对象的值在 React 状态下不会立即更新,任何人都可以解决这个问题吗?
- python - 检查二叉树是否围绕其中心对称-如何将节点值打印为调试?
- c# - 使用通用响应模型找不到路由异常
- django - cpanel是否需要外部命令才能运行redis
- swift - 异步等待调用后更新 UI
- c++ - 尝试使用地图将像素数据从 cpu 复制到 gpu 一切运行正常,但屏幕为空 directx
- python-3.x - ArangoDB AQL:在 python 中运行 AQL 查询时出现错误,没有要绘制的数字数据
- c# - Wix MSI 确实创建了我需要的路径,但代码在调试中有效
- python - RuntimeError: 给定组=1,大小为 [64, 1, 19] 的权重,预期输入 [64, 187, 1] 有 1 个通道,但得到了 187 个通道(CNN 分类器)