RecyclerView выпускает MediaPlayer, когда активируется onStop - PullRequest
0 голосов
/ 06 апреля 2020

Я создаю простое приложение с одним TextView и ImageButton представлением, я использую RecyclerView для отображения списка их пар, поэтому я написал свой Пользовательский адаптер и держатель для просмотра. Но у меня есть одна проблема, как выпустить MediaPlayer , когда пользователь переходит на домашний экран. Потому что я инициализирую MediaPlayer внутри адаптера и не знаю, как вызвать освобождение, если действие прекращается. Вот мой код:

Класс активности:

public class NumbersActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_word_list);

        List<Word> words = new ArrayList<>();
        words.add(new Word("one", R.raw.number_one));
        words.add(new Word("two", R.raw.number_two));
        words.add(new Word("three", R.raw.number_three));
        words.add(new Word("four", R.raw.number_four));
        words.add(new Word("five", R.raw.number_five));

        LinearLayoutManager numbersListLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        RecyclerView listView = findViewById(R.id.word_list);
        listView.setLayoutManager(numbersListLayoutManager);
        listView.setAdapter(new WordAdapter(this, words));
    }
}

Класс адаптера:

public class WordAdapter extends RecyclerView.Adapter<WordAdapter.ViewHolder> {

        private Context context;
        private List<Word> words;
        private MediaPlayer mediaPlayer;

        public WordAdapter(Context context, List<Word> words) {
            this.context = context;
            this.words = words;
        }

        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View viewItem = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
            return new ViewHolder(viewItem);
        }

        @Override
        public void onViewDetachedFromWindow(@NonNull ViewHolder holder) {
            super.onViewDetachedFromWindow(holder);
            stopPlaying();
        }

        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
            holder.englishTranslation.setText(this.words.get(position).getDefaultTranslation());

            holder.itemView.setOnClickListener((view) -> {
                stopPlaying();
                mediaPlayer = MediaPlayer.create(this.context, this.words.get(position).getAudioResourceId());
                mediaPlayer.setOnCompletionListener((mp) -> {
                    stopPlaying();
                });
                mediaPlayer.start();
            });
        }

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

        public class ViewHolder extends RecyclerView.ViewHolder {
            TextView englishTranslation;
            ImageButton playButton;

            public ViewHolder(View wordView) {
                super(wordView);
                this.englishTranslation = wordView.findViewById(R.id.english_text_view);
                this.playButton = wordView.findViewById(R.id.play_button);
            }
        }

        private void stopPlaying() {
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
                mediaPlayer.reset();
                mediaPlayer.release();
                mediaPlayer = null;
            }
        }
    }

Должен ли я передавать объект MediaPlayer в адаптер и контролировать его состояние из класса активности? Или это можно сделать изнутри адаптера?

Ответы [ 2 ]

1 голос
/ 06 апреля 2020

Вы можете остановить медиаплеер, используя метод stopPlaying. Чтобы заставить его работать, вам нужно создать экземпляр адаптера, а когда onStop() вызывать, просто вызвать метод из адаптера, и все готово !!!

Создать экземпляр адаптера

private WordAdapter mWordAdapter;

 mWordAdapter = new WordAdapter(this, words)
 listView.setAdapter(mWordAdapter)

переопределить метод onStop в вашей деятельности

 @Override
    protected void onStop() {
        super.onStop(); 
        if(mWordAdapter!=null){
            mWordAdapter.stopPlaying()
        }
    }

Сделать метод stopPlaying publi c, чтобы вы могли получить к нему доступ через объект.

public void stopPlaying() {
            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
                mediaPlayer.reset();
                mediaPlayer.release();
                mediaPlayer = null;
            }
        }
1 голос
/ 06 апреля 2020
@Override
    public void onViewDetachedFromWindow(@NonNull ViewHolder holder) {
        super.onViewDetachedFromWindow(holder);
        stopPlaying();
    }

Здесь вы устанавливаете, чтобы остановить игрока.

Он срабатывает, когда ViewHolder не виден на экране

Вы должны иметь свой экземпляр игрока внутри Activity и управлять им by Callbacks интерфейса (шаблон слушателя) от адаптера.

Также для производительности будет намного лучше иметь один медиаплеер вместо множества внутри VH

Обратный вызов должен выглядеть следующим образом:

interface PlayableItemCallback {
 void onItemVisible(int position);

 void onPlay(int position);

 void onStop(int position);
}

Реализуйте его в своей деятельности и используйте его для управления вашим MediaPlayer, передав его адаптеру. Код деятельности:

public class NumbersActivity extends AppCompatActivity implements PlayableItemCallback {
    MediaPlayer mediaPlayer;
    Adapter adapter = Adapter(this)

    //    .............
    @Override
    public void onItemVisible(int position) {

        // do stuff with player
    }

    @Override
    public void onPlay(int position) {
        // do stuff with player
    }

    @Override
    public void onStop(int position) {
        // do stuff with player
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...