英文:
RecyclerView release MediaPlayer when activity onStop is triggered
问题
以下是您提供的内容的翻译部分:
活动类:
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 对象传递给适配器,并从活动类中控制它的状态?还是可以在适配器内部执行此操作呢?
英文:
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. But I have one problem how to release MediaPlayer when a user goes to the home screen. Because I initialize MediaPlayer inside adapter and I don't know how to trigger release if activity is being stopped. Here's my code:
Activity 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:
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 ? Or is it possible to do it from inside of adapter?
答案1
得分: 3
@Override
public void onViewDetachedFromWindow(@NonNull ViewHolder holder) {
super.onViewDetachedFromWindow(holder);
stopPlaying();
}
在这里,你正在设置停止播放器。
当`ViewHolder`在屏幕上不可见时触发。
你应该在Activity中拥有播放器实例,并通过适配器的接口回调(监听器模式)来控制它。
此外,使用单个媒体播放器而不是在`VH`内部使用多个对于性能会更好。
回调应该像这样:
```java
interface PlayableItemCallback {
void onItemVisible(int position);
void onPlay(int position);
void onStop(int position);
}
在你的Activity中实现它,并在适配器中传递它以控制你的MediaPlayer。Activity代码:
public class NumbersActivity extends AppCompatActivity implements PlayableItemCallback {
MediaPlayer mediaPlayer;
Adapter adapter = new Adapter(this);
// .............
@Override
public void onItemVisible(int position) {
// 对播放器进行操作
}
@Override
public void onPlay(int position) {
// 对播放器进行操作
}
@Override
public void onStop(int position) {
// 对播放器进行操作
}
}
<details>
<summary>英文:</summary>
@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 screen
You should have your player instance inside Activity and control it by Interface callbacks (listener pattern) from adapter.
Also it is going to be much better for performance to have single media player instead of many inside `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. 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
}
}
</details>
# 答案2
**得分**: 1
你可以使用 `stopPlaying` 方法来停止媒体播放器。要使其正常工作,您需要创建适配器的实例,并在 `onStop()` 调用时从适配器中调用该方法,完成操作!!!
**创建适配器实例**
```java
private WordAdapter mWordAdapter;
mWordAdapter = new WordAdapter(this, words);
listView.setAdapter(mWordAdapter);
在您的活动中覆盖 onStop
方法
@Override
protected void onStop() {
super.onStop();
if(mWordAdapter!=null){
mWordAdapter.stopPlaying();
}
}
将 stopPlaying
方法设置为公共方法,以便通过对象访问它。
public void stopPlaying() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}
}
英文:
You can stop the media player using stopPlaying
method. 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!!!
Create the instance of the adapter
private WordAdapter mWordAdapter;
mWordAdapter = new WordAdapter(this, words)
listView.setAdapter(mWordAdapter)
override the onStop method in your activity
@Override
protected void onStop() {
super.onStop();
if(mWordAdapter!=null){
mWordAdapter.stopPlaying()
}
}
Make stopPlaying
method public so you can access it via object.
public void stopPlaying() {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.reset();
mediaPlayer.release();
mediaPlayer = null;
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论