1

Я установив OnClickListener в cardviews на моем ViewHolder:Как вызвать служебное вложение из MainActivity через фрагмент?

public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View view = LayoutInflater.from(parent.getContext()) 
       .inflate(R.layout.list_item, parent, false); 
     view.setBackgroundResource(mBackground); 
     return new ViewHolder(view); 
    } 

    @Override 
    public void onBindViewHolder(final ViewHolder holder, int position) { 
     holder.mBoundString = mValues.get(position); 
     holder.mTextView.setText(mValues.get(position)); 

     holder.mView.setOnClickListener(new View.OnClickListener() { 
      @Override 

      public void onClick(View v) { 


       MainActivity mActivity= new MainActivity(); 
       mActivity.onClickPlayButton(v); 
      } 
     }); 

     Glide.with(holder.mImageView.getContext()) 
       .load(Stations.getRandomCheeseDrawable()) 
       .fitCenter() 
       .into(holder.mImageView); 
    } 

Это мой onClickPlayButton на MainActivity:

public void onClickPlayButton(View view) { 
     radioServiceBinder.play(); 
    } 

Это код обслуживания:

public class RadioService extends Service implements OnErrorListener, OnCompletionListener, OnPreparedListener, OnInfoListener { 

private MediaPlayer mediaPlayer; 
private List<String> radioStreamURL = new ArrayList<>(); 
private int radioStreamingIndex = 0; 

public static final String MODE_CREATED = "CREATED"; 
public static final String MODE_DESTROYED = "DESTROYED"; 
public static final String MODE_PREPARED = "PREPARED"; 
public static final String MODE_STARTED = "STARTED"; 
public static final String MODE_PLAYING = "PLAYING"; 
public static final String MODE_PAUSED = "PAUSED"; 
public static final String MODE_STOPPED = "STOPPED"; 
public static final String MODE_COMPLETED = "COMPLETED"; 
public static final String MODE_ERROR = "ERROR"; 
public static final String MODE_BUFFERING_START = "BUFFERING_START"; 
public static final String MODE_BUFFERING_END = "BUFFERING_END"; 

private boolean isPrepared = false; 

private final IBinder binder = new RadioBinder(); 

    @Override 
    public void onCreate() { 
     // add stations to the list 

     radioStreamURL.add("http://momori.animenfo.com:8000/"); 
     radioStreamURL.add("http://momori.animenfo.com:8000/"); 
     radioStreamURL.add("http://momori.animenfo.com:8000/"); 

     /* Create MediaPlayer when it starts for first time */ 
     mediaPlayer = new MediaPlayer(); 
     mediaPlayer.setOnCompletionListener(this); 
     mediaPlayer.setOnErrorListener(this); 
     mediaPlayer.setOnPreparedListener(this); 
     mediaPlayer.setOnInfoListener(this); 

     sendBroadcast(new Intent(MODE_CREATED)); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     mediaPlayer.stop(); 
     mediaPlayer.reset(); 
     isPrepared = false; 
     sendBroadcast(new Intent(MODE_DESTROYED)); 
    } 


    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 
     sendBroadcast(new Intent(MODE_STARTED)); 

     /* Starts playback at first time or resumes if it is restarted */ 
     if(mediaPlayer.isPlaying()) 
      sendBroadcast(new Intent(MODE_PLAYING)); 
     else if(isPrepared) { 
      sendBroadcast(new Intent(MODE_PAUSED)); 
     } 

     return Service.START_STICKY; 
    } 


    @Override 
    public void onPrepared(MediaPlayer _mediaPlayer) { 
     /* If radio is prepared then start playback */ 
     sendBroadcast(new Intent(MODE_PREPARED)); 
     isPrepared = true; 
     play(); 
    } 

    @Override 
    public void onCompletion(MediaPlayer mediaPlayer) { 
     /* When no stream found then complete the playback */ 
     mediaPlayer.stop(); 
     mediaPlayer.reset(); 
     isPrepared = false; 
     sendBroadcast(new Intent(MODE_COMPLETED)); 
    } 

    public void prepare() { 
     /* Prepare Async Task - starts buffering */ 
     try { 
      mediaPlayer.setDataSource(radioStreamURL.get(radioStreamingIndex)); 
      mediaPlayer.prepareAsync(); 
     } catch (IllegalArgumentException e) { 
      e.printStackTrace(); 
     } catch (IllegalStateException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void nextStation(){ 
     changeStation(radioStreamingIndex+1); 
    } 

    public void prevStation(){ 
     changeStation(radioStreamingIndex-1); 
    } 

    public void changeStation(int stationIndex){ 
     if(stationIndex > 0 && stationIndex < radioStreamURL.size()){ 
      radioStreamingIndex = stationIndex; 
      stop(); 
      play(); 
     } 
    } 

    public void play() { 
     if(isPrepared) { 
      mediaPlayer.start(); 
      System.out.println("RadioService: play"); 
      //sendBroadcast(new Intent(MODE_PLAYING)); 
     } 
     else 
     { 
      //sendBroadcast(new Intent(MODE_STARTED)); 
      prepare(); 
     } 
    } 

    public void pause() { 
     mediaPlayer.pause(); 
     System.out.println("RadioService: pause"); 
     sendBroadcast(new Intent(MODE_PAUSED)); 
    } 

    public void stop() { 
     mediaPlayer.stop(); 
     mediaPlayer.reset(); 
     isPrepared = false; 
     System.out.println("RadioService: stop"); 
     sendBroadcast(new Intent(MODE_STOPPED)); 
    } 

    @Override 
    public boolean onInfo(MediaPlayer mp, int what, int extra) { 
     /* Check when buffering is started or ended */ 
     if(what == MediaPlayer.MEDIA_INFO_BUFFERING_START) { 
      sendBroadcast(new Intent(MODE_BUFFERING_START)); 
     } 
     else if(what == MediaPlayer.MEDIA_INFO_BUFFERING_END) { 
      sendBroadcast(new Intent(MODE_BUFFERING_END)); 
     } 

     return false; 
    } 


    @Override 
    public boolean onError(MediaPlayer mp, int what, int extra) { 
     sendBroadcast(new Intent(MODE_ERROR)); 
     switch (what) { 
      case MediaPlayer.MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK: 
       Log.v("ERROR","MEDIA ERROR NOT VALID FOR PROGRESSIVE PLAYBACK " + extra); 
       break; 
      case MediaPlayer.MEDIA_ERROR_SERVER_DIED: 
       Log.v("ERROR","MEDIA ERROR SERVER DIED " + extra); 
       break; 
      case MediaPlayer.MEDIA_ERROR_UNKNOWN: 
       Log.v("ERROR","MEDIA ERROR UNKNOWN " + extra); 
       break; 
     } 
     return false; 
    } 


    @Override 
    public IBinder onBind(Intent intent) { 
     return binder; 
    } 

    /* Allowing activity to access all methods of RadioService */ 
    public class RadioBinder extends Binder { 
     RadioService getService() { 
      // Return this instance of RadioService so clients can call public methods 
      return RadioService.this; 
     } 
    } 

} 

Когда я щелкните по нему, я получил эту ошибку в logcat: java.lang.NullPointerException: попытка вызвать виртуальный метод ... RadioService.play() 'в ссылке на нулевой объект.

Я не думаю, что в методе play() есть что-то неправильное.

Я хочу, чтобы OnClickListener или onClickPlayButton вызывали метод play() из моего класса сервиса, привязанного к моей MainActivity. Как я могу это достичь? Я застрял в этой проблеме.

+0

я принимаю ваш 'ViewHolder' принадлежит адаптеру, который принадлежит вашему «Фрагменту», который находится в вашей «MainActivity»? Передайте фрагменты 'Context' в ваш' ViewHolder' и вызовите там '((MainActivity) context.getActivity()). OnClickPlayButton (v)'. – kphil

+0

Да. Я попробую это и опубликую результаты здесь. Спасибо за помощь. –

+0

@kphil, метод 'getActivity()' в классе 'Context' отсутствует. Ваш код должен быть без него: '((MainActivity) контекст) .onClickPlayButton (v);' Смотрите мой обновленный ответ; – mohax

ответ

0

ошибка Yours здесь

MainActivity mActivity= new MainActivity(); 
mActivity.onClickPlayButton(v); 

Вы пытаетесь вызвать метод нового экземпляра класса Activitys. Но вы должны вызывать метод текущего, запущенного экземпляра вашей активности. Поэтому вы должны отправить ссылку на свою активность на адаптер и вызвать свой метод на нем.

Как я понимаю, вы инициализируете переменные и связываете свою службу в OnCreate или onResume вашей активности. Но эти методы не вызывают adter, вы создаете новый экземпляр класса MainActivity;

UPD_0:

Так ваши адаптеры класс должен быть такой:

public class YOURS_ADAPTERS_CLASS_NAME extends RecyclerView.Adapter<YOURS_ADAPTERS_CLASS_NAME.ViewHolder> 
{ 
    Context ctx; 

public YOURS_ADAPTERS_CLASS_NAME(Context ctx) 
{ 
    this.ctx=ctx; 
} 

///other lines of yours code 

Так что теперь у вас есть экземпляр вами работаете активность внутри ваши адаптеры класса. Теперь вы должны бросить его к вашему activitys класса и вызвать метод твой так:

MainActivity mActivity= (MainActivity) ctx; 
mActivity.onClickPlayButton(v); 

Кроме того, вам не нужно (как я могу видеть) аргумент в методе onClickPlayButton()

+0

Спасибо, что помогли мне. Я попробовал это вместо: MainActivity.radioServiceBinder.play(); Но radioServiceBinder является нестатическим полем и не может быть отсрочен от статического содержимого. –

+0

@WendellKrohling См. Обновленный ответ. – mohax

Смежные вопросы