【问题标题】:Release ExoPlayer in RecyclerView在 RecyclerView 中释放 ExoPlayer
【发布时间】:2019-01-12 03:25:08
【问题描述】:

我正在 RecyclerView 中实现 ExoPlayer。但是在滚动视频时停止,但不是音频。

如何在 RecyclerView 中释放 ExoPlayer?或者我怎样才能获得回收对象的位置,以便能够释放 ExoPlayer?

这是我的数据对象

public class            enter code here           Video {
    private String url;
    private Context context;
    Boolean playWhenReady = false;
    int currentWindow = 0;
    long playbackPosition = 0;
    ExoPlayer player;

    public Video(String url, Context context) {
        this.url = url;
        this.context = context;
    }

    public void setCurrentWindow(int currentWindow) {
        this.currentWindow = currentWindow;
    }

    public void setPlaybackPosition(long playbackPosition) {
        this.playbackPosition = playbackPosition;
    }

    public void setPlayWhenReady(Boolean playWhenReady) {
        this.playWhenReady = playWhenReady;
    }

    public void setPlayer(ExoPlayer player) {
        this.player = player;
    }

    public ExoPlayer getPlayer() {
        return player;
    }

    public String getUrl() {
        return url;
    }

    public Context getContext() {
        return context;
    }

    public Boolean getPlayWhenReady() {
        return playWhenReady;
    }

    public int getCurrentWindow() {
        return currentWindow;
    }

    public long getPlaybackPosition() {
        return playbackPosition;
    }
}

这是我的适配器类: 我尝试使用 onViewRecycled() 方法,但因为我没有得到位置,我无法释放播放器。

public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.ViewHolder> {
    private ArrayList<Video> mDataset;


    public static class ViewHolder extends RecyclerView.ViewHolder {
        public PlayerView mExoPlayer;

        public ViewHolder(View itemView) {
            super(itemView);
            mExoPlayer = itemView.findViewById(R.id.video_view);
        }
    }

    public VideoAdapter(ArrayList<Video> myDataset) {
        mDataset = myDataset;
    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View itemView=LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_item, parent, false);

        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int position) {


        initPlayer(holder,position);

    }

    private void initPlayer(ViewHolder holder,int position) {
        mDataset.get(position).setPlayer(ExoPlayerFactory.newSimpleInstance(
                new DefaultRenderersFactory(mDataset.get(position).getContext()),
                new DefaultTrackSelector(), new DefaultLoadControl()));

        holder.mExoPlayer.setPlayer(mDataset.get(position).getPlayer());

        mDataset.get(position).getPlayer().setPlayWhenReady(mDataset.get(position).getPlayWhenReady());
        mDataset.get(position).getPlayer().seekTo(mDataset.get(position).getCurrentWindow(), mDataset.get(position).getPlaybackPosition());

        Uri uri = Uri.parse(mDataset.get(position).getUrl());
        MediaSource mediaSource = buildMediaSource(uri);
        mDataset.get(position).getPlayer().prepare(mediaSource, true, false);
    }

    private MediaSource buildMediaSource(Uri uri) {

        return new ExtractorMediaSource.Factory(
                new DefaultHttpDataSourceFactory("exoplayer-codelab")).
                createMediaSource(uri);
    }


    @Override
    public int getItemCount() {
        return mDataset.size();
    }

    @Override
    public void onViewRecycled(@NonNull ViewHolder holder) {
        super.onViewRecycled(holder);
    }


}

【问题讨论】:

  • 你能分享完整的代码我如何在回收站视图中使用 exo 播放器。
  • 我做了一个新项目,可以帮助所有正在尝试的人:github.com/paulo-coutinho/rvplayer

标签: android android-recyclerview exoplayer


【解决方案1】:
  holder.yourplayername.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
            @Override
            public void onViewAttachedToWindow(View v) {

            }

            @Override
            public void onViewDetachedFromWindow(View v) {
                holder.yourplayername.getPlayer().stop();

            }
        });

你好。我希望这段代码对你有帮助,因为对我有用。

【讨论】:

  • 它会停止视频,但如果您的视频在半屏上仍然在播放,在屏幕上停止视频后它仍然在播放,想要播放它显示空白?这是什么解决方案
【解决方案2】:

系统不能容纳多个ExoPlayer 实例。它可以抛出OOM Exception。因此,当用户看不到该项目时,您必须释放ExoPlayer。在这种情况下,我建议你使用RecyclerView.Adapter中的波纹管方法

override fun onViewDetachedFromWindow(holder: ViewHolder) {
    holder.itemView.player?.stop()
    holder.itemView.player?.release()
    holder.itemView.player = null
    super.onViewDetachedFromWindow(holder)
}

然后,在ViewHolder 类中你应该检查,如果是player == null,你必须初始化它。

【讨论】:

    【解决方案3】:

    我认为当播放器的视图被回收时释放播放器是最干净的。

    适配器类:

    @Override
    public void onViewRecycled(@NonNull ViewHolder holder) {
        int position = holder.getAdapterPosition();
        if (mDataset.get(position) != null) {
            mDataset.get(position).getPlayer().release();
        }
        super.onViewRecycled(holder);
    }
    

    【讨论】:

    • 如果您 release() 播放器,则它不能再次使用,因此如果您打算在回收视图中重复使用播放器,这不是一个好主意。
    • @ChristopherPerry 然后如何释放播放器并重新实例化它?
    • @Arjun 您应该将播放器的单个实例存储在父 Activity/Fragment 中,在 onResume() 方法中实例化播放器并在 onStop() 方法中释放播放器。 Here 是实现此功能的官方演示。它还有很多其他的东西,但特别是 MainActivity.java 和 PlayerManager.java。
    • 此外,Christopher Perry 说的 the player cannot be used after release 是正确的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多