作为一个android开发者,service大家应该已经接触过了,接触Android的第一节课,就是将Android的四大组件,那么作为四大组件之一的service,你是否足够了解呢?
service和thread的区别你是否知道?service真的能执行长时间的后台操作么?
你是否知道startservice和bindservice的区别呢?
service的生命周期,我们是否应该主动结束一个service呢?service是否会导致内存泄露呢?
上边是关于service的一些问题,问题1,我们已经在之前的博客上讲解过,详细内容见博客http://blog.csdn.net/u014088294/article/details/49907385
关于问题4,也可以参考我们之前的文章 ,http://blog.csdn.net/u014088294/article/details/44279399
我们主要解答问题2,startservice与bindservice的区别。
Developer上提到,service主要有两种形式,
上边的started呢,对应与startservice,bound对应于bindservice,他们都是启动service的方式。
我们可以通过startservice来启动一个service,启动后,service在后台运行。通常来说,该service是无法返回结果的(这也是与bindservice的区别之一),比如我们可以下载一个文件。
和startservice对应的是stopservice,我们可以来显式的结束一个service。
service的生命周期也比较简单,和startservice相关的有三个函数,分别是onCreate,onStartCommand,onDestory。
当我们首次startserivce启动一个service的时候,会调用service的onCreate函数,创建该服务,然后调用onStartCommand函数,执行操作。如果我们多次通过startservice启动服务,那么onCreate只会调用一次,直接调用onStartCommand。
我们可以调用stopsevice来结束一个service。同样,我们也可以多次调用(第一次调用已经结束,但是后来继续调用并不会产生异常)。
当一个service通过startservice启动后,它就独立于调用者而运行(也就是说,调用者的生命周期和它的生命周期没有关系),因此呢,service应该在任务完成的时候调用stopSelf函数或者调用者stopservice来结束该服务。
Developer上提到,当我们的service执行完的时候,为了避免消耗系统资源或电量,应该结束该service。否则,该服务将会一直运行在后台,直到设备内存不足等原因把他关闭掉。
然而,startservice并不能解决我们所有的需求,比如,我有时候,需要service的返回结果,我需要和service交互,startservice显然不能完成。那么我们可以使用到bindservice
Developer这样提到,
A bound service offers a client-server interface that allows components to interact with the service, send requests, get results, and even do so across processes with interprocess communication (IPC).
我们可以利用bindservice来和service绑定,绑定后,我们可以和service交互,发送请求,得到结果甚至执行IPC通信。
那么,我们应该如何使用bindservice呢?
按照上边的步骤,我们的代码如下,
1. 重载onBinder并返回一个IBinder对象。在LocalBinder中,提供getSercive方法,返回service实例。
public class LocalBinder extends Binder {
MyService getService() {
return MyService.this;
}
}
private final IBinder mBinder = new LocalBinder();
@Override
public IBinder onBind(Intent intent) {
Log.i(TAG, "onBind");
return mBinder;
}
2.调用者中新建ServiceConnection接口,在onServiceConnected方法中,将IBinder对象转为LocalBinder对象,并调用其getService方法,得到Service。
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
mBoundService = ((MyService.LocalBinder) service).getService();
}
public void onServiceDisconnected(ComponentName className) {
mBoundService = null;
}
};
3.调用者执行bindservice,其中mConnection为ServiceConnection接口。
bindService(new Intent(MainActivity.this,MyService.class), mConnection, Context.BIND_AUTO_CREATE);
当用户执行bindservice后,bind的结果会回调mConnection接口,若bind成功,就会回调onServiceConnected方法,然后我们在此方法中,得到了Service实例,得到Service实例后,然后我们就可以和Service交互了。
我们继续完善代码,在Service的onCreate方法中,我们新建一个线程,每隔1s,计数器加1.其中count为成员变量,表示当前计数值,threadDisable表示是否service关闭。
new Thread(new Runnable() {
// @Override
public void run() {
while (!threadDisable) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
count++;
System.out.println("CountService Count is " + count);
}
}
}).start();
然后,我们在Service中新建一个方法,返回计数值。
public int getCount() {
return count;
}
那么我们在调用者中,就可以利用上边得到的mBoundService来调用getCount方法,达到与service交互的目的。
项目地址,https://github.com/KingPaul/ServiceDemo