【问题标题】:Android - MediaPlayer will not release when called from another classAndroid - 从另一个类调用时,MediaPlayer 不会释放
【发布时间】:2018-12-04 10:35:55
【问题描述】:

我有一个 RecyclerView,我在其中添加元素并可以单击它们来播放声音。如果我在 Adapter 类中创建所有 MediaPlayer 方法,所有内容都会被正确释放,并且一次只会播放一个音频。

//this works (code in the adapter class)
private MediaPlayer mMediaPlayer;

//release if not playing
public void releaseMediaPlayer() {
    // if no sound is playing
    if (mMediaPlayer != null) {
        Log.d("rEEEEEEEEEEEEEEEEEEE", "releaseMediaPlayer: ");
        mMediaPlayer.release();
        mMediaPlayer = null;
    }
}

//release media player on sound finish
public MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        releaseMediaPlayer();
    }
};
// on click listener code
releaseMediaPlayer();
mMediaPlayer = MediaPlayer.create(context, word.getmAudioResourceId());
mMediaPlayer.start();
mMediaPlayer.setOnCompletionListener(mCompletionListener);

但是,如果我使用单独的类,每当我调用 release 方法时,它不会在开始时释放,因此会同时播放多个声音。它在完成时正常释放

public class MediaPlay {
private MediaPlayer mMediaPlayer;

public void setmMediaPlayer(MediaPlayer mMediaPlayer) {
    this.mMediaPlayer = mMediaPlayer;
}

public MediaPlayer getmMediaPlayer() {
    return mMediaPlayer;
}

//release if not playing
public void releaseMediaPlayer() {
    // if no sound is playing
   if (mMediaPlayer != null) {
        Log.d("rEEEEEEEEEEEEEEEEEEEEEEEEEEE", "releaseMediaPlayer: ");
        mMediaPlayer.release();
        mMediaPlayer = null;
    }
}

//release media player on sound finish
public MediaPlayer.OnCompletionListener mCompletionListener = new MediaPlayer.OnCompletionListener() {
    @Override
    public void onCompletion(MediaPlayer mediaPlayer) {
        releaseMediaPlayer();
    }
};

}

使用类时的onclicklistener

final MediaPlay m = new MediaPlay();
m.releaseMediaPlayer(); 
m.setmMediaPlayer(MediaPlayer.create(context, word.getmAudioResourceId()));
m.getmMediaPlayer().start();
m.getmMediaPlayer().setOnCompletionListener(m.mCompletionListener);

我尝试在 clickListener 之外创建 MediaPlay 对象,但没有结果。我基本上是在尝试创建一个单独的类,这样我就可以从我的活动中调用它,这样我就可以在 onStop 方法中停止声音。 任何意见将不胜感激。

使用点击监听器编辑 1 个完整的视图

    MediaPlay m;
    public ViewHolder(@NonNull View itemView) {
        super(itemView);
        //play specific sound for each list item
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d("ViewHolder: ", String.valueOf(getAdapterPosition()));
                Word word = Words.get(getAdapterPosition());
                if (word.hasAudio()) {

                    /*releaseMediaPlayer(); // stop multiple playbacks at once
                    mMediaPlayer = MediaPlayer.create(context, word.getmAudioResourceId());
                    mMediaPlayer.start();
                    mMediaPlayer.setOnCompletionListener(mCompletionListener); //cleanup*/

                    if (m != null)
                        m.releaseMediaPlayer();

                    m = new MediaPlay();
                    //m.releaseMediaPlayer(); //TODO still plays duplicate sounds, release method not working when called like this
                    m.setmMediaPlayer(MediaPlayer.create(context, word.getmAudioResourceId()));
                    m.getmMediaPlayer().start();
                    m.getmMediaPlayer().setOnCompletionListener(m.mCompletionListener);
                }
            }
        });

        name = itemView.findViewById(R.id.nameT);
        type = itemView.findViewById(R.id.typeT);
        img = itemView.findViewById(R.id.imgV);
    }

【问题讨论】:

    标签: java android android-mediaplayer


    【解决方案1】:

    我已经使用回调修改了您的源代码。

    请仔细查看 MyViewHolder 类和 MyAdapter 的 onCreateViewHolder 方法:)。

    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
        private Context mContext;
        private String[] mDataSet;
        private MediaPlayer mMediaPlayer;
    
        public static class MyViewHolder extends RecyclerView.ViewHolder {
            private TextView mTextView;
            private OnMediaPlayRequestedListener mOnMediaPlayRequestedListener;
    
            public MyViewHolder(TextView v, OnMediaPlayRequestedListener listener) {
                super(v);
    
                mTextView = v;
                mTextView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (mOnMediaPlayRequestedListener != null) {
                            mOnMediaPlayRequestedListener.onMediaPlayRequested(R.raw.{resource name});
                        }
                    }
                });
    
                mOnMediaPlayRequestedListener = listener;
            }
    
            private interface OnMediaPlayRequestedListener {
                void onMediaPlayRequested(int resourceId);
            }
        }
    
        public MyAdapter(Context context, String[] myDataset) {
            mContext = context;
            mDataSet = myDataset;
        }
    
        @NonNull
        @Override
        public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            TextView view =
                    (TextView) LayoutInflater.from(parent.getContext()).inflate(R.layout.my_text_view, parent, false);
    
            MyViewHolder holder = new MyViewHolder(
                    view,
                    new MyViewHolder.OnMediaPlayRequestedListener() {
                        @Override
                        public void onMediaPlayRequested(int resourceId) {
                            if (mMediaPlayer != null) {
                                mMediaPlayer.stop();
                                mMediaPlayer.release();
                            }
    
                            mMediaPlayer = MediaPlayer.create(mContext, resourceId);
                            mMediaPlayer.start();
                            mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                                @Override
                                public void onCompletion(MediaPlayer mediaPlayer) {
                                    mediaPlayer.release();
                                }
                            });
                        }
                    });
    
    
            return holder;
        }
    
        @Override
        public void onBindViewHolder(@NonNull MyViewHolder viewHolder, int position) {
            viewHolder.mTextView.setText(mDataSet[position]);
        }
    
        @Override
        public int getItemCount() {
            return mDataSet.length;
        }
    }
    

    【讨论】:

    • 我刚刚尝试按照您的建议修改我的代码,但遗憾的是它没有奏效。多个音频文件仍在同时播放。
    • 感谢您的检查。您能否附上更多代码您是如何设置点击侦听器的?
    • 感谢您的帮助。我在创建点击监听器的地方添加了我的整个视图。被注释掉的代码块可以正常工作(它会在新的点击时停止先前的音频并停止当前的音频)。
    • 你好@Jinzo,我修改了答案。你能检查并尝试一下吗?
    • 我设法通过添加 mMedialayer.stop() 来解决所有问题,就像你建议的那样,我的 releaseMediaPlayer() 函数存储在 MediaPlay 类中,并使整个方法和类中的 mMediaPlay 变量都是静态的.现在我通过导入类而不是通过对象直接调用释放函数。
    猜你喜欢
    • 2014-03-24
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多