在学习Service与Activity交互,写了一个Demo,结果在Activity中调用service中的方法时报空指针异常,代码如下:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private ProgressListener mlistener;
private ProgressBar mDownloadProgress;
private MyDownloadService myDownloadService;
private Button mDownloadButton;
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d("Devin", "onServiceConnected");
myDownloadService = ((MyDownloadService.DownloadBinder)service).getService();
if (myDownloadService == null) {
Log.d("Devin", "myDownloadService == null");
}
myDownloadService.setProgressListener(
new ProgressListener() {
@Override
public void onProgress(int progress) {
mDownloadProgress.setProgress(progress);
}
}
);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDownloadProgress = (ProgressBar) findViewById(R.id.download_progress);
Intent intent = new Intent(MainActivity.this, MyDownloadService.class);
boolean result = bindService(intent, conn, Context.BIND_AUTO_CREATE);
Log.d("Devin", "After bindservice, result:" + result);
myDownloadService.startDownload();
}
}
MyDownloadService.java:
/**
* Created by Devin on 2016/6/12.
*/
public class MyDownloadService extends Service{
ProgressListener progressListener = null;
private final int MAX_PROGRESS = 100;
private int progress = 0;
private DownloadBinder mBinder = new DownloadBinder();
@Nullable
@Override
public IBinder onBind(Intent intent) {
// mBinder = new DownloadBinder();
Log.d("Devin", "Service onBind.");
return mBinder;
}
public void setProgressListener(ProgressListener listener) {
this.progressListener = listener;
}
public void startDownload() {
new Thread() {
@Override
public void run() {
while (progress < MAX_PROGRESS) {
progress += 5;
if (progressListener != null) {
progressListener.onProgress(progress);
} else {
throw new NullPointerException();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
@Override
public void onCreate() {
super.onCreate();
Log.d("Devin", "Service onCreate.");
}
public class DownloadBinder extends Binder {
public MyDownloadService getService() {
return MyDownloadService.this;
}
}
}
抛出空指针异常,定位在MainAcitivty中的这行:
myDownloadService.startDownload();
发现加在ServiceConnection中的Log以及加在MyDownloadService中的Log均未执行。也就是ServiceConnection中的方法未执行,没有得到service的实例,所以会出现此问题。
后来将MainActivity的onCreate更改如下即解决问题,不过只不过是对service的调用放到了回掉的onClick方法里,为什么问题就解决了呢?
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDownloadProgress = (ProgressBar) findViewById(R.id.download_progress);
Intent intent = new Intent(MainActivity.this, MyDownloadService.class);
boolean result = bindService(intent, conn, Context.BIND_AUTO_CREATE);
Log.d("Devin", "After bindservice, result:" + result);
// myDownloadService.startDownload();
mDownloadButton = (Button) findViewById(R.id.download_btn);
mDownloadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myDownloadService.startDownload();
}
});
}
推测是由于bindService时,调用bindService的Context还未初始化完成(onCreate未执行完毕),导致连接不能够正常创建,而当使用回掉方法来实现时,由于Activity已经初始化完毕,而链接建立成功,也自然可以得到service的实例,所以不会出现异常。
具体情况还需要对Activity初始化流程以及bindService的相关流程有一定了解后再进行分析。先写到这里,请容小生过后再继续跟踪。