简体   繁体   English

RecyclerView在触发activity onStop时释放MediaPlayer

[英]RecyclerView release MediaPlayer when activity onStop is triggered

I'm creating a simple app with one TextView and ImageButton view, I am using RecyclerView to display list of pairs of these so I wrote my custom adapter and view holder.我正在使用一个TextViewImageButton视图创建一个简单的应用程序,我正在使用RecyclerView显示这些对的列表,所以我编写了我的自定义适配器和视图支架。 But I have one problem how to release MediaPlayer when a user goes to the home screen.但是当用户进入主屏幕时,我有一个问题如何释放MediaPlayer Because I initialize MediaPlayer inside adapter and I don't know how to trigger release if activity is being stopped.因为我在适配器内部初始化MediaPlayer ,如果活动停止,我不知道如何触发释放。 Here's my code:这是我的代码:

Activity class:活动 class:

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

Adapter class:适配器 class:

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

Should I pass MediaPlayer object to adapter and control it's state from activity class?我是否应该将 MediaPlayer object 传递给适配器并从活动 class 控制它的 state? Or is it possible to do it from inside of adapter?或者是否可以从适配器内部进行?

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

Here you are setting to stop your player.在这里你设置停止你的播放器。

It is triggered when ViewHolder is not visible on screenViewHolder在屏幕上不可见时触发

You should have your player instance inside Activity and control it by Interface callbacks (listener pattern) from adapter.您应该在 Activity 中拥有您的播放器实例,并通过来自适配器的接口回调(侦听器模式)来控制它。

Also it is going to be much better for performance to have single media player instead of many inside VH此外,在VH中使用单个媒体播放器而不是多个播放器的性能会更好

Callback should look like this:回调应如下所示:

interface PlayableItemCallback {
 void onItemVisible(int position);

 void onPlay(int position);

 void onStop(int position);
}

Implement it in your activity and use it to control your MediaPlayer with passing it in to adapter.在您的活动中实现它并使用它来控制您的 MediaPlayer,并将其传递给适配器。 Activity code:活动代码:

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

You can stop the media player using stopPlaying method.您可以使用stopPlaying方法停止媒体播放器。 To make it work you have to create the instance of the adapter and when onStop() call just call the method from the adapter and you are done!!!为了让它工作,你必须创建适配器的实例,当onStop()调用时,只需从适配器调用方法,你就完成了!!!

Create the instance of the adapter创建适配器的实例

private WordAdapter mWordAdapter;

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

override the onStop method in your activity覆盖活动中的 onStop 方法

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

Make stopPlaying method public so you can access it via object.公开stopPlaying方法,以便您可以通过 object 访问它。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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