【问题标题】:Exoplayer stop not working in RecyclerView in FragmentExoplayer 停止在 Fragment 的 RecyclerView 中不起作用
【发布时间】:2022-03-15 01:30:40
【问题描述】:

我正在为我的 RecyclerView 使用 FirestorePagingAdapter。

当片段关闭时,我尝试在 onStop、onPasue、onDestroy 方法中停止 exoplayer,但是 它不能正常工作,它只停止 Recycler 视图中的最后一个视频,但我不明白 这里的主要问题是什么。

   @Override
    public void onStop() {
        super.onStop();
        adapter.stopListening();
        if (HomeVideoHolder.simpleExoPlayer != null) {
            HomeVideoHolder.simpleExoPlayer.stop();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        adapter.stopListening();
        if (HomeVideoHolder.simpleExoPlayer != null) {
            HomeVideoHolder.simpleExoPlayer.stop();

        }
    }

    @Override
    public void onPause() {
        super.onPause();
        adapter.stopListening();
        if (HomeVideoHolder.simpleExoPlayer != null) {
            HomeVideoHolder.simpleExoPlayer.stop();

        }

我在 HomeVideoHolder 中将 simpleExoplayer 声明为公共静态。

   public static PlayerView videoViewpath;
    public static SimpleExoPlayer simpleExoPlayer;

我还尝试停止、释放、setPlayWhenReady(false) 并寻求视频结尾 停止 exoplayer。

但是每种方法都给了我相同的结果。他们只停止 recyclerView 的最后一个视频。

请给我这个问题的解决方案......

我的适配器代码...

        adapter=new FirestorePagingAdapter<HomeClass, HomeVideoHolder>(options) {
            @Override
            protected void onBindViewHolder(@NonNull HomeVideoHolder holder, int position, @NonNull HomeClass model) {
              
             
                    holder.setVideoView(getActivity(),model.getAd(),model.getpId(),model.getcUid(),model.getUid(),model.getPic(),model.getVideo(),model.getcT());
                
            }

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

            @Override
            protected void onLoadingStateChanged(@NonNull LoadingState state) {
                switch (state) {
                    case LOADING_INITIAL:
                        // The initial load has
                        swipeRefreshLayout.setRefreshing(true);
                        break;
                    // ...
                    case LOADING_MORE:
                        // The adapter has started to load an additional page
                        vLoadMore.setVisibility(View.VISIBLE);
                        break;
                    // ...
                    case LOADED:
                        // The previous load (either initial or additional) completed
                        swipeRefreshLayout.setRefreshing(false);
                        vLoadMore.setVisibility(View.INVISIBLE);
                        break;

                    // ...
                    case FINISHED:
                        vLoadMore.setVisibility(View.INVISIBLE);
                        break;
                    case ERROR:
                        // The previous load (either initial or additional) failed. Call
                        adapter.retry();
                        swipeRefreshLayout.setRefreshing(true);
                        // the retry() method in order to retry the load operation.
                        break;
                    // ...
                }
            }


        };


我的 viewHolder 代码....

 public void setVideoView(Activity activity,String ad, String pId, String cUid, String uid, String pic, String video, String cT) {
        final CircleImageView chanelProfile=view.findViewById(R.id.cPicH);
        final TextView chanelName=view.findViewById(R.id.cNameH);
        final TextView videoCaption=view.findViewById(R.id.vDesH);
        final ImageView videoThreeDot=view.findViewById(R.id.threeDotHome);

        Pkey=pId;
        user=FirebaseAuth.getInstance().getCurrentUser().getUid();

        videoCaption.setText(cT);

        setPlayer(video);
}

    private void setPlayer(String video) {

        if (playCode.equals("true")) {

            LoadControl loadControl = new DefaultLoadControl();
            BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
            TrackSelector trackSelector = new DefaultTrackSelector(
                    new AdaptiveTrackSelection.Factory(bandwidthMeter)
            );
            simpleExoPlayer = ExoPlayerFactory.newSimpleInstance(
                    view.getContext(), trackSelector, loadControl
            );
            DefaultHttpDataSourceFactory factory = new DefaultHttpDataSourceFactory(
                    "Video"
            );
            ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
            MediaSource mediaSource = new ExtractorMediaSource(Uri.parse(Video),
                    factory, extractorsFactory, null, null
            );
            videoViewpath.setPlayer(simpleExoPlayer);
            videoViewpath.setKeepScreenOn(true);
            simpleExoPlayer.prepare(mediaSource);
            simpleExoPlayer.setPlayWhenReady(false);
            simpleExoPlayer.addListener(new Player.DefaultEventListener() {
                @Override
                public void onTimelineChanged(Timeline timeline, Object manifest, int reason) {
                    super.onTimelineChanged(timeline, manifest, reason);
                }

                @Override
                public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
                    super.onTracksChanged(trackGroups, trackSelections);
                }

                @Override
                public void onLoadingChanged(boolean isLoading) {
                    super.onLoadingChanged(isLoading);
                }

                @Override
                public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
                    super.onPlayerStateChanged(playWhenReady, playbackState);
                    switch (playbackState) {

                        case Player.STATE_BUFFERING:
                            progressBar.setVisibility(View.VISIBLE);
                            break;
                        case Player.STATE_ENDED:

                            break;
                        case Player.STATE_IDLE:
                            break;
                        case Player.STATE_READY:
                            addViwes();
                            progressBar.setVisibility(View.INVISIBLE);
                            break;
                        default:
                            break;

                    }
                }

                @Override
                public void onRepeatModeChanged(int repeatMode) {
                    super.onRepeatModeChanged(repeatMode);

                }

                @Override
                public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) {
                    super.onShuffleModeEnabledChanged(shuffleModeEnabled);
                }

                @Override
                public void onPlayerError(ExoPlaybackException error) {
                    super.onPlayerError(error);
//                simpleExoPlayer.prepare(mediaSource);
//                simpleExoPlayer.setPlayWhenReady(false);
                }

                @Override
                public void onPositionDiscontinuity(int reason) {
                    super.onPositionDiscontinuity(reason);
                }

                @Override
                public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {
                    super.onPlaybackParametersChanged(playbackParameters);
                }

                @Override
                public void onSeekProcessed() {
                    super.onSeekProcessed();
                }
            });

        }else {
                simpleExoPlayer.stop();
                simpleExoPlayer.release();
            simpleExoPlayer.clearVideoSurface();
            videoViewpath.setPlayer(null);
             }
    }



【问题讨论】:

    标签: java android android-recyclerview exoplayer2.x


    【解决方案1】:
    1. 不要将PlayerViewSimpleExoPlayer 声明为static,这是错误的方法...您只保留对最后一个视频播放器实例的引用,并且您希望所有这些实例都暂停/停止。每个HomeViewHolder 应该只保留自己的玩家引用,static 字段在引用保持类的所有实例中只保留一个实例(“所有者”,HomeViewHolder

    2. onPauseonStoponDestroy 中删除所有static 播放器停止代码,播放器实例(非static)无论如何都无法访问

    3. 覆盖适配器中的onViewDetachedFromWindow(HomeVideoHolder holder) 和/或onViewRecycled(HomeVideoHolder holder) 方法,在此暂停/停止附加到单个HomeVideoHolder 的一个播放器实例

    让适配器在单个项目被回收/分离时停止每个玩家,不仅在销毁Activity/Fragment 时。目前你可能有一些内存泄漏,因为开始播放的玩家可能会留在内存中播放一些视频,而你没有参考它(仅对最后一个,static 字段如上)释放资源......当你销毁@ 987654340@ 然后附加到它的适配器将回收/销毁所有当前存在的HomeViewPagers,请确保您可以在onDestroyrecyclerView.setAdapter(null)(在super 调用之前)。还要检查此模式(回收视图)如何与 RecyclerView.Adapter 的所有可覆盖方法中的一些 Log 调用一起使用,以 on... 开头(例如,如 3 中所述)

    【讨论】:

    • 您应该在主要的Activity 中保留一个对SimpleExoPlayer 的引用,并将该引用传递给需要它的地方,否则您可能会遇到decoder error
    【解决方案2】:

    您应该保留一个 ExoPlayer 实例。在 Activity 中创建它,然后通过构造函数传递给适配器。这是我的代码: 适配器: class VideoAdapter( private val mContext: Context, val exoPlayer: ExoPlayer, options: FirestoreRecyclerOptions&lt;VideoModel?&gt;) :[...]

    exoPlayer
    .also { exoPlayer ->
                    styledPlayerView.player = exoPlayer
                    exoPlayer.seekTo(currentWindow, playbackPosition)
                    styledPlayerView.setShowBuffering(StyledPlayerView.SHOW_BUFFERING_WHEN_PLAYING)
                    styledPlayerView.useController = false
                    exoPlayer.repeatMode = Player.REPEAT_MODE_ONE
    
                }
    

    活动:

    private lateinit var exoPlayer: ExoPlayer [...]
    exoPlayer = ExoPlayer.Builder(requireContext())
            .build() [...]
    videoAdapter = VideoAdapter(requireContext(), exoPlayer, options)
    

    然后在我的活动 onStop() 方法中:

    override fun onStop() {
        super.onStop()
        videoAdapter.stopListening()
        exoPlayer.release()
    }
    

    【讨论】:

      猜你喜欢
      • 2021-06-18
      • 1970-01-01
      • 1970-01-01
      • 2022-09-24
      • 2018-01-10
      • 2018-03-22
      • 2019-01-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多