2017-02-07 1 views
0

Ich versuche, eine RecyclerView mit Audio-Nachrichten zu implementieren und diese Audiodateien abzuspielen. Zuvor war ich auf ein Problem fest, wenn ich Spiel ändere und Bild auf ImageButton, so I found this solution and changed my code accordingly. pausiere, aber jetzt stehe ich einem anderen Problem gegenüber. Immer wenn ich den Ton abspiele, ändert sich das Bild in Pause, und wenn ich erneut auf diese Schaltfläche klicke, erhalte ich einen Fehler: pause called in state 8. Ich weiß, was das Problem verursacht, kann aber die Lösung nicht herausfinden. Hier ist meine onBindViewHolder:MediaPlayer Pause im Zustand 8 aufgerufen

@Override 
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 
      ((MyChatMediaViewHolder) holder).bindData(mChats.get(position), position); 
} 

Hier ist meine MyChatMediaViewHolder Klasse:

private class MyChatMediaViewHolder extends RecyclerView.ViewHolder { 
    private TextView txtUserAlphabet, timer; 
    private ImageView play; 
    private SeekBar seekBar; 
    ProgressBar progressBar; 
    RelativeLayout media_chat; 
    Chat chat = null; 

    public MyChatMediaViewHolder(View itemView) { 
     super(itemView); 
     play = (ImageView) itemView.findViewById(R.id.play); 
     seekBar = (SeekBar) itemView.findViewById(R.id.seekbar); 
     txtUserAlphabet = (TextView) itemView.findViewById(R.id.text_view_user_alphabet); 
     progressBar = (ProgressBar) itemView.findViewById(R.id.progressUpdate); 
     media_chat = (RelativeLayout) itemView.findViewById(R.id.chat_media); 
     timer = (TextView) itemView.findViewById(R.id.timer); 
     Log.e("TAG111", "bindData: "); 

     play.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       isPlay = !isPlay; 
       //Handling for background selection state changed 
       int previousSelectState=mSelectedItemPosition; 
       mSelectedItemPosition = getAdapterPosition(); 
       //notify previous selected item 
       notifyItemChanged(previousSelectState); 
       //notify new selected Item 
       notifyItemChanged(mSelectedItemPosition); 
      } 
     }); 
    } 

    public void bindData(Chat chat, int currentPosition) { 
     this.chat = chat; 
     MediaPlayer mediaPlayer = new MediaPlayer(); 
     MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever(); 

     try { 
      mediaPlayer.setDataSource(chat.mediaUrlLocal); 
      metaRetriever.setDataSource(chat.mediaUrlLocal); 
      mediaPlayer.prepare(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     String duration = 
       metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); 
     long dur = Long.parseLong(duration); 
     String seconds = String.valueOf((dur % 60000)/1000); 

     String minutes = String.valueOf(dur/60000); 
     String out = minutes + ":" + seconds; 

     timer.setText(out); 

     if(currentPosition == mSelectedItemPosition) { 
      Log.e("pause", "bindData: " + mediaPlayer.isPlaying()); 
      if(isPlay) { 
       mediaPlayer.start(); 
       play.setImageResource(android.R.drawable.ic_media_pause); 
      } else { 
       mediaPlayer.pause(); 
       play.setImageResource(android.R.drawable.ic_media_play); 
      } 

     } else { 
      play.setImageResource(android.R.drawable.ic_media_play); 
     } 
    } 
} 

Das Problem hier ist meiner Meinung nach: neue MediaPlayer Instanz jedes Mal Play-Taste angeklickt wird erstellt wird, so dass, wenn ich versuche, Um zu pausieren, wird erneut ein neuer Medienplayer erstellt, der nie gestartet wurde. Die Frage lautet: Wo soll ich die neue MediaPlayer-Instanz erstellen?

Antwort

1

Zunächst ist Ihr Zweck RecyclerView.Adapter Ihre Sicht aufzublasen, Sie sollten hier nicht Ihre Geschäftslogik schreiben.

Zweitens sollten Sie nur eine Instanz von Media Player verwenden. Sie sollten Ihren Media Player innerhalb Ihrer Activity oder Fragment initialisieren.

Erstellen Sie ein Schnittstellengerät in Ihrem Activity oder Fragment und übergeben Sie die Referenz an Ihren Adapter. Wann immer Sie Audio wiedergeben möchten, verwenden Sie Ihre Schnittstelle, um Ihren Audiodateipfad oder -stream an Activity oder Fragment zu delegieren, Ihren Medienplayer zurückzusetzen oder freizugeben und Ihr Audio abzuspielen.

1

Ich denke, die beste Lösung (wenn Sie nur ein Audio zu einer Zeit spielen müssen) wäre, nur eine Instanz von MediaPlayer in RecyclerView.Adapter zu behalten und Sie können auch dort eine Karte, wo der Schlüssel Position und Wert ist wäre eine einfache Klasse mit: flag - isPlaying, Dauer (wenn du deinen Song gespielt hast und ihn unterbrochen hast, möchtest du ihn nicht von Anfang an starten, sondern von wo aus du ihn pausiert hast), usw. Wenn du also auf und ab scrollst kann den Stand der Ansichten beibehalten, die abgespielt/angehalten wurden.

Verwandte Themen