简体   繁体   中英

How to implement exoplayer with recyclerview and viewpager2?

I am creating a video feed and was using the VideoView to preview video in the viewpager2. But because it was slow, I tried to shift to exoplayer. Everything works kind of okay but the problem is that every video in the adapter loads at once and when I swipe from the viewpager, the video does not pause. Here is the code for the adapter:

public class VideosAdapter extends RecyclerView.Adapter<VideosAdapter.VideoViewHolder> {

    private List<VideoItem> videoItems;

    public VideosAdapter(List<VideoItem> videoItems) {
        this.videoItems = videoItems;
    }

    @NonNull
    @Override
    public VideoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new VideoViewHolder(
               LayoutInflater.from(parent.getContext()).inflate(
                       R.layout.item_container_video,
                       parent,
                       false
               )
        );
    }



    @Override
    public void onBindViewHolder(@NonNull VideoViewHolder holder, int position) {
      holder.setVideoData(videoItems.get(position));
    }

    

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


    static class VideoViewHolder extends RecyclerView.ViewHolder {

        PlayerView playerView;
        TextView video__description;
        ProgressBar videoProgressBar;
        SimpleExoPlayer simpleExoPlayer;
        LoopingMediaSource loopingMediaSource;
        DefaultHttpDataSourceFactory factory;
        ExtractorsFactory extractorsFactory;
        BandwidthMeter bandwidthMeter;
        TrackSelector trackSelector;

        public VideoViewHolder(@NonNull View itemView) {
            super(itemView);
            playerView = itemView.findViewById(R.id.player__view);
            video__description = itemView.findViewById(R.id.video__description);
            videoProgressBar = itemView.findViewById(R.id.videoLoader);
            factory = new DefaultHttpDataSourceFactory("exoplayer_video");
            extractorsFactory = new DefaultExtractorsFactory();
            bandwidthMeter = new DefaultBandwidthMeter();
            trackSelector = new DefaultTrackSelector(
                    new AdaptiveTrackSelection.Factory(bandwidthMeter)
            );
        }

        void setVideoData(VideoItem videoItem) {
            Uri videoUrl =Uri.parse(videoItem.videoURL);
            simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(videoItem.context, trackSelector);
            MediaSource mediaSource = new ExtractorMediaSource(videoUrl,factory,extractorsFactory,null,null);
            loopingMediaSource = new LoopingMediaSource(mediaSource);
            playerView.setPlayer(simpleExoPlayer);
            playerView.setKeepScreenOn(true);
            simpleExoPlayer.prepare(loopingMediaSource);
            simpleExoPlayer.setPlayWhenReady(true);
            video__description.setText(videoItem.videoDescription);
            simpleExoPlayer.addListener(new Player.DefaultEventListener() {
                @Override
                public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                    super.onPlayerStateChanged(playWhenReady, playbackState);
                    if(playbackState==Player.STATE_BUFFERING) {
                        videoProgressBar.setVisibility(View.VISIBLE);
                    } else if(playbackState==Player.STATE_READY) {
                        videoProgressBar.setVisibility(View.GONE);
                    }
                }

                @Override
                public void onPlayerError(ExoPlaybackException error) {
                    super.onPlayerError(error);
                }
            });
        }
    }
}


Here is the code for the videoItems Class:

public class VideoItem {
    public String videoURL, videoDescription;
    public Context context;

    public VideoItem(String videoURL, String videoDescription, Context context) {
        this.videoURL = videoURL;
        this.videoDescription = videoDescription;
        this.context = context;
    }
}

And here is the code for setting the adapter:

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        // Inflate the layout for this fragment
        View root = inflater.inflate(R.layout.fragment_first, container, false);


        final ViewPager2 videosViewPager = root.findViewById(R.id.videosViewPager);

            List<VideoItem> videoItems = new ArrayList<>();

VideoItem videoItemFirst = new VideoItem("https://www.infinityandroid.com/videos/video1.mp4","Hello World", requireActivity().getApplicationContext());
            videoItems.add(videoItemFirst);

            VideoItem videoItemSecond = new VideoItem("https://www.infinityandroid.com/videos/video2.mp4","Hello World", requireActivity().getApplicationContext());
            videoItems.add(videoItemSecond);

            VideoItem videoItemThird = new VideoItem("https://www.infinityandroid.com/videos/video3.mp4","Hello World", requireActivity().getApplicationContext());
            videoItems.add(videoItemThird);

videosViewPager.setAdapter(new VideosAdapter(videoItems));


return root;
}

Here is the layout file:


<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".fragments.firstFragment"
    >

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/videosViewPager"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toTopOf="parent"
        app:layout_constraintEnd_toStartOf="parent"
         />

</androidx.constraintlayout.widget.ConstraintLayout>

It seems to be loading all the videos at once when the fragment is loaded and when I swipe to get to the next video, the previous video does not get paused. How to fix this? Is there a better method? Hope you will answer.

This code is based on ExoPlayer with RecyclerView:

https://github.com/NehaKushwah993/InstagramVideoFeedClone/blob/main/README.md

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM