Exoplayer перестает работать в RecyclerView во фрагменте

Я использую FirestorePagingAdapter для своего RecyclerView.

при закрытии фрагмента я пытаюсь остановить exoplayer в методе onStop, onPasue, onDestroy, но он не работает должным образом. Он останавливает только последнее видео в представлении 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();

        }

Я объявил simpleExoplayer как общедоступную статику в HomeVideoHolder.

   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);
             }
    }




person SNPL NETWORK    schedule 10.12.2020    source источник


Ответы (1)


  1. не объявляйте PlayerView и SimpleExoPlayer как static, это неправильный подход ... вы сохраняете ссылку только на последний экземпляр видеоплеера и хотите, чтобы все они приостановили / остановили все. каждый HomeViewHolder должен содержать только собственную ссылку на игрока, поле static хранит только один экземпляр во всех экземплярах класса хранения ссылок (владелец, HomeViewHolder)

  2. удалите весь ваш static код остановки проигрывателя из onPause, onStop и onDestroy, экземпляр проигрывателя (не static) в любом случае будет недоступен

  3. переопределить onViewDetachedFromWindow(HomeVideoHolder holder) и / или onViewRecycled(HomeVideoHolder holder) метод (ы) в адаптере, в этом месте приостановить / остановить этот экземпляр одного игрока, прикрепленный к одиночному HomeVideoHolder

пусть адаптер останавливает каждого игрока, когда отдельный предмет перерабатывается / отсоединяется, а не только при уничтожении _15 _ / _ 16_. в настоящее время у вас, вероятно, есть утечки памяти, так как запущенные игроки могут оставаться в памяти, воспроизводя какое-то видео, и у вас нет ссылки на него (только на последнее, поле static, как указано выше) для освобождения ресурсов ... когда вы уничтожаете RecyclerView затем адаптер прикрепленный к нему, перерабатывает / уничтожает все существующие в настоящее время HomeViewPager. проверьте, как этот шаблон (повторное использование представлений) работает с некоторыми Log вызовами, чтобы быть уверенным, что вы можете recyclerView.setAdapter(null) в onDestroy (перед super вызовом)

person snachmsm    schedule 10.12.2020
comment
Вы должны сохранить одну ссылку на SimpleExoPlayer в главном Activity и передать эту ссылку туда, где это необходимо, иначе вы, вероятно, столкнетесь с ошибка декодера - person lasec0203; 14.07.2021