应用程序第二次在列表视图的适配器中播放音频时崩溃

Posted

技术标签:

【中文标题】应用程序第二次在列表视图的适配器中播放音频时崩溃【英文标题】:App crashes onPlaying audio in Adapter of listview second time 【发布时间】:2015-01-04 02:17:39 【问题描述】:

我的课程由包含曲目列表的列表视图组成。每个列表项由按钮播放和暂停组成。它应该在单击播放时播放曲目并在单击暂停时停止曲目。我没有使用不同的按钮....我是仅使用一个按钮,该按钮会在单击黑白播放和暂停时更改其文本,并相应地起作用。 我面临以下问题- 单击播放确实会播放曲目,但是当我通过单击暂停停止曲目然后尝试播放任何曲目时,应用程序崩溃并显示以下错误,显示非法状态异常

致命异常:主要

java.lang.IllegalStateException
        at android.media.MediaPlayer._setDataSource(Native Method)
        at android.media.MediaPlayer.setDataSource(MediaPlayer.java:966)
        at android.media.MediaPlayer.setDataSource(MediaPlayer.java:926)
        at xyz.SoundCloudAdapter$1.onClick(SoundCloudAdapter.java:86)
        at android.view.View.performClick(View.java:4091)
        at android.view.View$PerformClick.run(View.java:17072)
        at android.os.Handler.handleCallback(Handler.java:615)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:153)
        at android.app.ActivityThread.main(ActivityThread.java:5086)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:511)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584)
        at dalvik.system.NativeStart.main(Native Method)

声音类适配器 公共类 SoundCloudAdapter 扩展 ArrayAdapter 实现 MediaPlayer.OnPreparedListener ArrayList soundcloudList; LayoutInflater vi; int 资源;

    public static MediaPlayer mMediaPlayer;
    public SoundCloudAdapter(Context context, int resource, ArrayList<SoundCloud> objects)
    
        super(context, resource, objects);
        vi = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        Resource = resource;
        soundcloudList = objects;
        mMediaPlayer = new MediaPlayer();
        mMediaPlayer.setOnPreparedListener(this);
    


    @Override
    public View getView(final int position, View convertView, ViewGroup parent)
    
        final ViewHolder holder;

        // convert view = design

        View v = convertView;
        if (v == null)
        
            holder = new ViewHolder();
            v = vi.inflate(Resource, null);

            holder.textview = (TextView) v.findViewById(R.id.name);
            holder.btn = (Button) v.findViewById(R.id.button);
            holder.btn2 = (Button) v.findViewById(R.id.button2);
       holder.textview2 = (TextView) v.findViewById(R.id.email);
            v.setTag(holder);
        
        else
        
            holder = (ViewHolder) v.getTag();
        
        holder.textview.setText(soundcloudList.get(position).getTitle());
        holder.textview2.setText(soundcloudList.get(position).getId());

        holder.btn.setOnClickListener(new View.OnClickListener() 

            @Override
            public void onClick(View v) 

                notifyDataSetChanged();

                if (holder.btn.getText().toString().equalsIgnoreCase("Play"))
                
                holder.btn.setText("Pause");


                    mMediaPlayer.setAudiostreamType(AudioManager.STREAM_MUSIC);
                    try
                    
                        mMediaPlayer.setDataSource("http://api.soundcloud.com/tracks/"+soundcloudList.get(position).getId()+"/stream?client_id=xyz");
                        mMediaPlayer.prepareAsync();
                    
                    catch (IllegalArgumentException e)
                    
                        e.printStackTrace();

                    
                    catch (IOException e)
                    
                        e.printStackTrace();

                    
                    notifyDataSetChanged();
                
                else if (holder.btn.getText().toString().equalsIgnoreCase("Pause"))
                
                    holder.btn.setText("Play");
                    if(mMediaPlayer.isPlaying()) 
                        mMediaPlayer.stop();

                    
                    mMediaPlayer.release();
                    notifyDataSetChanged();
                






            
        );

        return v;

    

    @Override
    public void onPrepared(MediaPlayer mp) 
        mp.start();
    

    static class ViewHolder
    

        public TextView textview;
        public Button btn;
        public Button btn2;
        public TextView textview2;


    



如果我声明

mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setOnPreparedListener(this); inside onClick() 

曲目不会暂停

【问题讨论】:

我认为您忘记在暂停按钮单击侦听器时释放 MediaPlayer。 @HareshChhelana 我没有使用第二个按钮..错误地我忘记删除代码..我只使用一个按钮,它会在单击黑白播放和暂停和相应的功能时更改其文本。 .检查更新的代码 @HareshChhelana 查看更新的问题..谢谢 @HareshChhelana 现在跟踪点击暂停时不会暂停 【参考方案1】:

尝试在播放和暂停时处理每个列表项的 MediaPlayer 状态,也无需将可能影响列表项状态的 viewHolder 对象声明为 final。

public class SoundCloudAdapter extends BaseAdapter

    private MediaPlayer mMediaPlayer;
    private Context context;
    private ArrayList<SoundCloud> soundcloudList;

    public SoundCloudAdapter(Context context, ArrayList<SoundCloud> soundcloudList)
        this.context=context;
        this.soundcloudList = soundcloudList;
    

    @Override
    public long getItemId(int position) 
        return position;
    

    @Override
    public int getCount() 
        return soundcloudList.size();
    

    @Override
    public Object getItem(int position) 
        return soundcloudList.get(position);
    

    @Override
    public View getView(final int position, View convertView, ViewGroup parent)
    
        ViewHolder holder;
        if (convertView == null)
            holder = new ViewHolder();
            convertView = LayoutInflater.from(context).inflate(R.layout.resource, null);
            holder.textview = (TextView) convertView.findViewById(R.id.name);
            holder.textview2 = (TextView) convertView.findViewById(R.id.email);
            holder.btn = (Button) convertView.findViewById(R.id.button);
            convertView.setTag(holder);
        else
            holder = (ViewHolder) convertView.getTag();
        

        holder.textview.setText(soundcloudList.get(position).getTitle());
        holder.textview2.setText(soundcloudList.get(position).getId());
        holder.btn.setOnClickListener(new View.OnClickListener() 

            @Override
            public void onClick(final View v) 

                if(((Button)v).getText().toString().equals("Play"))
                    try
                        mMediaPlayer = new MediaPlayer();
                        mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                        mMediaPlayer.setDataSource("http://api.soundcloud.com/tracks/"+soundcloudList.get(position).getId()+"/stream?client_id=e13865f9debacb5f96375fdd96b7fa1b");
                        mMediaPlayer.prepareAsync();
                        mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() 
                            @Override
                            public void onPrepared(MediaPlayer mp) 
                                mp.start();
                                ((Button)v).setText("Pause");
                            
                        );
                        mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() 
                            @Override
                            public void onCompletion(MediaPlayer mp) 
                                mMediaPlayer.release();
                                mMediaPlayer = null;
                                ((Button)v).setText("Play");
                            
                        );
                    catch (Exception e)
                        e.printStackTrace();
                    
                else
                    mMediaPlayer.release();
                    mMediaPlayer = null;
                    ((Button)v).setText("Play");
                
                notifyDataSetChanged();

            
        );

        return convertView;

    

    static class ViewHolder
    
        public TextView textview;
        public TextView textview2;
        public Button btn;
    


【讨论】:

当我点击“播放”按钮轨道星星播放和按钮文本更改为暂停但我面临的一个问题是如果我向下滚动然后再次向上滚动然后我再次看到按钮文本播放虽然它应该暂停,因为轨道当前正在播放..这意味着按钮状态没有被保存并且向下滚动并再次出现片段的一部分再次加载。我应该如何解决这个问题? 我已经解决了我问的上述问题,但我遇到的问题是,如果我把 mMediaPlayer = new MediaPlayer();在 holder.btn.setOnClickListener() 的 onClick() 中,然后单击多个播放按钮将开始同时播放多个曲目..所以我把 mMediaPlayer = new MediaPlayer();在 SoundCloudAdapter 构造函数中,并面临以下问题 ***.com/questions/26947105/…【参考方案2】:

看看这段代码:

holder.btn.setText("Play");
if(mMediaPlayer.isPlaying()) 
    mmMediaPlayer.stop();

mMediaPlayer.release();
notifyDataSetChanged();

如果你想恢复播放,你不应该停止并释放MediaPlayer,然后你必须再次初始化它。您应该只调用pause() 方法,它就是这样做的,它会停止播放,但会保留轨道中的当前位置并且不会释放资源。

另外,删除release()call。由于您仍想再次使用相同的曲目(下次单击播放时)。

编辑:您还应该检查在“播放”上运行的代码,您不需要每次要恢复播放时都设置数据源,只需第一次。

【讨论】:

以上是关于应用程序第二次在列表视图的适配器中播放音频时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

核心图像过滤器的输出图像第二次在 UIImage 上运行时为零

当我打开 iPhone 3G 时,应用程序第二次在闪屏上崩溃

第二次在图上运行时,广度/深度优先搜索导致崩溃

阵列适配器在第二个活动中崩溃

无法使用 MediaPlayer 对象在 Android 中播放许多音频文件

为什么当我第二次在Android Studio中使用导航启动动作时,导航目的地丢失了?