我在我的ViewHolder上将一个OnClickListener设置为cardviews:
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);
}
这是我在MainActivity上的onClickPlayButton:
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()&#39;在null对象引用上。
我认为play()方法没有任何问题。
我希望OnClickListener或onClickPlayButton从绑定到MainActivity的Service类调用play()方法。我怎样才能做到这一点? 我坚持这个问题。
答案 0 :(得分:0)
你的错误
MainActivity mActivity= new MainActivity();
mActivity.onClickPlayButton(v);
您尝试调用Activitys类的新实例的方法。但是你应该调用当前的方法,运行你的活动实例。因此,您必须将对您的活动的引用发送到适配器并在其上调用您的方法。
据我了解,您初始化变量并在OnCreate或您的活动的onResume上绑定您的服务。但是这个方法没有被调用,所以你创建了一个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
所以现在你有你的实例在你的适配器类中运行活动。您现在应该将它转换为您的活动类并以这种方式调用您的方法:
MainActivity mActivity= (MainActivity) ctx;
mActivity.onClickPlayButton(v);
此外,您不需要(我可以看到)方法onClickPlayButton()