具有多个视图的RecyclerView中的Exoplayer

时间:2018-10-02 17:12:43

标签: android android-recyclerview callback recycler-adapter exoplayer

我有一个带有多个视图的RecyclerView。其中一个视图具有“播放”按钮和“搜索栏”,用于播放音频文件。最佳做法是,您是否在AudioViewHolder中实现ExoPlayer?还是在RecyclerView所在的活动中?

如果我在Activity中实现它,则在单击Activity上的Play / Pause按钮时,将从AudioViewHolder(适配器中的接口)发送回叫。 ExoPlayer.onPlayerStateChanged(STATE_ENDED)将无法访问“播放按钮视图”并更新按钮图像。

如何将ExoPlayer发送到AudioViewHolder,以便更新播放/暂停按钮的图像?

AudioChatItem

private void initPlayButton(File file) {
    playButton.requestFocus();
    playButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (isPlaying) {
                isPlaying = false;
                playButton.setImageResource(R.drawable.ic_play);
                audioControllerCallback.onStop();
            } else {
                isPlaying = true;
                playButton.setImageResource(R.drawable.ic_stop);
                audioControllerCallback.onPlay(file);
            }
        }
    });
}

ChatActivity

    private ChatMessagesAdapter.AudioControllerCallback audioControllerCallback =    new ChatMessagesAdapter.AudioControllerCallback() {
        @Override
        public void onPlay(File file) {
            prepareExoPlayerFromUri(Uri.parse(file.getAbsolutePath()));
            mExoPlayer.setPlayWhenReady(true);
        }

        @Override
        public void onStop() {
            mExoPlayer.setPlayWhenReady(false);
        }

        @Override
        public void onSeek(int progress) {
            mExoPlayer.seekTo(progress * 1000);
        }
    };

 private Player.EventListener eventListener = new Player.EventListener() {

         @Override
             public void onPlayerStateChanged(boolean playWhenReady, int     playbackState) {
              Log.i("EXO", "onPlayerStateChanged: playWhenReady = " +         String.valueOf(playWhenReady)
                    + " playbackState = " + playbackState);

            switch (playbackState) {
                case Player.STATE_ENDED:
                    Log.i("EXO", "Playback ended!");
                    //Here I need to access the playButton in my ViewHolder
                    audioControllerCallback.onStop();
                    mExoPlayer.seekTo(0);
                    break;
                case Player.STATE_READY:
                        Log.i("EXO", "ExoPlayer ready! pos: " +   mExoPlayer.getCurrentPosition()
                            + " max: " + stringForTime((int)  mExoPlayer.getDuration()));
//                  setProgress();
                    break;
                case Player.STATE_BUFFERING:
                    Log.i("EXO", "Playback buffering!");
                    break;
                case Player.STATE_IDLE:
                    Log.i("EXO", "ExoPlayer idle!");
                    break;
            }
        }
          ...
      }

1 个答案:

答案 0 :(得分:0)

Pode ser na活动。 哦,法蒂奥·法诺·塞斯迪奥·罗达·瓦里奥斯·阿迪奥斯·梅斯莫·速度,康考达?

它可能在“活动”中。 事实是,同时运行多个音频没有意义,您同意吗?

public class StepDetailFragment extends Fragment implements StepsViewModel.PlayerLifeCycle,
        StepsViewModel.StepsEventHandler {

    public static final String STEP_SELECTED = StepDetailFragment.class.getName().concat(".STEP_SELECTED");
    private static final String PLAYER_STATE = StepDetailFragment.class.getName().concat(".PLAYER_STATE");


    private FragmentStepsDetailBinding mBinding;
    private StepsViewModel mViewModel;

    private ExoPlayer mExoPlayer;
    private MediaSessionCompat mMediaSession;
    private PlaybackStateCompat.Builder mStateBuilder;
    private Long mPlayerPosition;

    public StepDetailFragment(){}


    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_steps_detail, container,
                false);
        if(getActivity() != null)
            mViewModel = StepsDetailsActivity.obtainViewModel(getActivity());
        return mBinding.getRoot();
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (getArguments() != null) {
            if (getArguments().containsKey(STEP_SELECTED)) {
                Step mCurrentStep = getArguments().getParcelable(STEP_SELECTED);
                if (mViewModel != null){
                    mViewModel.getCurrentStep().setValue(mCurrentStep);
                }
            }
        }
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        if(getActivity() != null && mViewModel == null)
            mViewModel = StepsDetailsActivity.obtainViewModel(getActivity());

        mViewModel.setPlayerLifeCycle(this);
        mViewModel.setStepsEventHandler(this);

        mBinding.setViewModel(mViewModel);
        mBinding.setEventHandler(new WeakReference<StepsViewModel.StepsEventHandler>(this));


        if (getArguments() != null) {
            if (getArguments().containsKey(STEP_SELECTED)) {
                Step mCurrentStep = getArguments().getParcelable(STEP_SELECTED);
                mViewModel.getCurrentStep().setValue(mCurrentStep);
            }
        }

        if (savedInstanceState != null) {
            if (savedInstanceState.containsKey(STEP_SELECTED)) {
                Step mCurrentStep = savedInstanceState.getParcelable(STEP_SELECTED);
                mViewModel.getCurrentStep().setValue(mCurrentStep);
            }
            if (savedInstanceState.containsKey(PLAYER_STATE)) {
                mPlayerPosition = savedInstanceState.getLong(PLAYER_STATE);
            }
        }

        mViewModel.getCurrentStep().observe(this, new Observer<Step>() {
            @Override
            public void onChanged(@Nullable Step step) {
                if (step != null) {

                    mBinding.setViewModel(mViewModel);
                    mBinding.setEventHandler(new WeakReference<StepsViewModel.StepsEventHandler>(
                            StepDetailFragment.this));

                    setupToolbar();
                    releasePlayer();

                }

            }
        });

        setupToolbar();
    }

    private void setupToolbar() {
        if (mViewModel.getCurrentStep().getValue() != null) {
            AppCompatActivity activity = (AppCompatActivity) this.getActivity();
            if (activity != null) {
                activity.setTitle(mViewModel.getCurrentStep().getValue().getShortDescription());
            }
        }
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putParcelable(STEP_SELECTED, mViewModel.getCurrentStep().getValue());
        if (mExoPlayer != null) {
            outState.putLong(PLAYER_STATE, mExoPlayer.getCurrentPosition());
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        releasePlayer();
    }

    @Override
    public void onSetupPlayer(SimpleExoPlayer exoPlayer) {
        if (isAdded()) {
            mExoPlayer = exoPlayer;
            mExoPlayer.addListener(new MyPlayerListener());
            if (mMediaSession == null) {
                initializeMediaSession();
            }
            if (mPlayerPosition != null) {
                mExoPlayer.seekTo(mPlayerPosition);
                mPlayerPosition = null;
            }
        }
    }

    @Override
    public void nextPositionClick() {
        mViewModel.nextStep();
    }

    @Override
    public void previousPositionClick() {
        mViewModel.prevStep();
    }

    private class MyPlayerListener implements Player.EventListener {

        @Override
        public void onTimelineChanged(Timeline timeline, Object manifest, int reason) { }

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

        @Override
        public void onLoadingChanged(boolean isLoading) { }

        @Override
        public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
            if (mExoPlayer != null) {
                if ((playbackState == Player.STATE_READY) && playWhenReady) {
                    mStateBuilder.setState(PlaybackStateCompat.STATE_PLAYING,
                            mExoPlayer.getCurrentPosition(), 1f);
                } else if ((playbackState == Player.STATE_READY)) {
                    mStateBuilder.setState(PlaybackStateCompat.STATE_PAUSED,
                            mExoPlayer.getCurrentPosition(), 1f);
                }
                mMediaSession.setPlaybackState(mStateBuilder.build());
            }
        }

        @Override
        public void onRepeatModeChanged(int repeatMode) { }

        @Override
        public void onShuffleModeEnabledChanged(boolean shuffleModeEnabled) { }

        @Override
        public void onPlayerError(ExoPlaybackException error) { }

        @Override
        public void onPositionDiscontinuity(int reason) {  }

        @Override
        public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) { }

        @Override
        public void onSeekProcessed() { }
    }

    private void initializeMediaSession() {
        if (getContext() != null) {
            mMediaSession = new MediaSessionCompat(getContext(), this.getClass().getSimpleName());
            mMediaSession.setFlags(
                    MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
                            MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
            mMediaSession.setMediaButtonReceiver(null);

            mStateBuilder = new PlaybackStateCompat.Builder()
                    .setActions(
                            PlaybackStateCompat.ACTION_PLAY |
                                    PlaybackStateCompat.ACTION_PAUSE |
                                    PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS |
                                    PlaybackStateCompat.ACTION_PLAY_PAUSE);

            mMediaSession.setPlaybackState(mStateBuilder.build());
            mMediaSession.setCallback(new MySessionCallback());
            mMediaSession.setActive(true);
        }
    }

    private class MySessionCallback extends MediaSessionCompat.Callback {
        @Override
        public void onPlay() {
            if (mExoPlayer != null) {
                mExoPlayer.setPlayWhenReady(true);
            }
        }

        @Override
        public void onPause() {
            if (mExoPlayer != null) {
                mExoPlayer.setPlayWhenReady(false);
            }
        }

        @Override
        public void onSkipToPrevious() {
            if (mExoPlayer != null) {
                mExoPlayer.seekTo(0);
            }
        }
    }

    private void releasePlayer() {
        if (mExoPlayer != null) {
            mExoPlayer.stop();
            mExoPlayer.release();
        }
        mExoPlayer = null;
    }

}