Выпустить ExoPlayer в RecyclerView

Я реализую ExoPlayer в RecyclerView. Но при прокрутке видео останавливается, а звук нет.

Как я могу выпустить ExoPlayer в RecyclerView? Или как я могу получить положение переработанного объекта, чтобы я мог выпустить 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 player в режиме ресайклера.

webaddicted 26.03.2020 13:41

Я создал новый проект, который может помочь всем, кто пытается это сделать: github.com/paulo-coutinho/rvplayer

Paulo Coutinho 10.04.2021 02:50
5
2
7 355
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 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(), его нельзя будет использовать снова, поэтому это не очень хорошая идея, если вы планируете повторно использовать проигрыватель в переработанном виде.

Christopher Perry 14.05.2019 00:01

@ChristopherPerry Как потом выпустить плеер и восстановить его?

Arjun 22.12.2019 19:43

@Arjun Вы должны сохранить единственный экземпляр проигрывателя в родительском Activity / Fragment, создавая экземпляр проигрывателя внутри метода onResume() и выпуская проигрыватель внутри метода onStop(). Здесь - официальная демонстрация, которая реализует это. У него есть куча других вещей, но особенно посмотрите на MainActivity.java и PlayerManager.java.

Taylor Venissat 23.12.2019 21:13

Кроме того, Кристофер Перри был прав, когда они заявили, что плеер нельзя использовать после релиза.

Taylor Venissat 23.12.2019 21:15

Система не может содержать несколько экземпляров 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, вы должны его инициализировать.

  holder.yourplayername.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
            @Override
            public void onViewAttachedToWindow(View v) {

            }

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

            }
        });

Привет. Надеюсь, этот код будет полезен для вас, потому что работает для меня.

спасибо, отлично сработало!

Vivek 08.01.2021 12:53

он останавливает видео, но если ваше видео на половине экрана все еще воспроизводится после остановки видео на экране снова, вы хотите воспроизвести его, показывайте пустым? что это за решение этого

Adnan haider 23.02.2021 12:05

Другие вопросы по теме