onCreate():在服务创建时调用
onStartCommande():在每次服务启动时调用(会被多次调用,但只有一个Service实例)
onDestroy():服务被销毁时调用,用于回收不再使用的资源
注意:如果想让服务自己停止,要调用stopSelf()
bindService(Intent i,ServiceConnection conn,int flags); ServiceConnection对象用于监听访问者和服务之间的连接情况,当连接成功时将回调该对象的onServiceConnected(ComponentName name,IBinder bind);当Service的宿主由于某种原因异常终止时,会调用该对象的onServiceDisconnected(ComponentName name)方法。
注意:当调用者通过unbindService接触绑定时,并不会调用onServiceDisconnected。
Service内有唯一一个抽象方法onBind(),自定义服务时必须实现它。这个方法可以让服务与活动联系更紧密,因为这个方法返回了一个IBinder对象,这个IBinder会传给上面onServiceConnected方法中的IBinder,这样访问者可以通过IBinder与服务进行通信。(IBinder相当于Service组件内部的钩子)
比如我们在MyService中提供一个下载功能,然后由活动决定何时开始下载以及随时查看下载进度。
public class BindService extends Service{
private MyBinder binder=new MyBinder();
//内部类MyBinder
public class MyBinder extends Binder//继承Binder类实现了一个IBinder对象(Binder是IBinder的实现类)
{
public int getCount() return 1;
}
@Override
public IBinder onBinder(Intent i) return binder;
@Override
public void onCreate(){}
>@Override
public boolean onUnbind(Intent i) return true;//
@Override
public void onDestroy(){}
}
public class MainActivity extends Activity
{
BindService.MyBinder binder;//保持所启动的Service的IBinder对象
private ServiceConnection conn=new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name,IBinder bind){
binder=(BindService.MyBinder) bind;
}
@Override
public void onServiceDisconnected(ComponentName name){}
}
@Override
public void onCreate(Bundle savaedInstanceState){
final Intent intent=new Intent(this,BindService.class);
bindService(intent,conn,Service.BIND_AUTO_CREATE);//flags,如果没有Service则自动创建一个
int c=bind.getCount();
}
}
bindService之后,先调用
Service的onCreate(),然后调用
onBind(),onBind()返回一个IBinder对象,然后调用
onServiceConnected()
onCreate():
onBind():不管连接了多少次,onBind只执行一次
onUnbind():被绑定的生命周期必须由访问者调用unBindService()才会解除绑定
onDestroy():
注意:
还有一种特殊情况。如果活动a用StartService启动了某服务:onCreate() ---> onStartCommand(),这时活动b用bindService()绑定该服务,之后解绑:onBind() ---> onServiceConnected() ---> onUnBind();然后又调用bindService再次绑定:onRebind()。能回调onRebind的前提除了服务需要由statService启动以外还需要onBind方法中返回true。我们还发现,这种同时用了start和bind的情况下,只unBindService,不会调用onDestroy,即服务不会终止。必须同时满足stop和unBind,服务才会终止。
对于第1点,我们可以使用多线程编程,在服务的onStartCommand方法或是BindService类的onCreate方法中中开启一个子线程去处理耗时任务,如果想要线程的任务执行完就停止服务,可以在run()的最后(任务处理完成后)调用stopSelf(),而IntentService就直接为我们创建了子线程执行耗时任务,处理异步请求的时候不需要自己去开启新的线程,可以减少写代码的工作量。
public abstract class IntentService extends Service {
private volatile Looper mServiceLooper;
private volatile ServiceHandler mServiceHandler;
private String mName;
private boolean mRedelivery;
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
这里面有一个Looper对象,用来在新的线程中启动一个消息循环,来检查是否有新的任务需要执行,ServiceHander最终会与这个Looper绑定,通过这个Handler向Looper发送消息。
public IntentService(String name) {
super();
mName = name;
}
@Override
public void onCreate() {
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
IntentService创建时就会创建并启动Handler线程(HandlerThread),然后再将Handler对象与此线程的Looper对象绑定。并把Looper对象mServiceLooper传给ServiceHandler
在IntentService的startCommand()方法中直接调用了onStart(),我们直接看onStart()的源码:
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
当调用startService的时候,就会产生一条附带startId和Intent的Message并发送到MessageQueue中,接下来Looper发现MessageQueue中有Message的时候,就会通知Handler调用handleMessage()处理消息,代码如下
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
handleMessage()中调用了 onHandleIntent((Intent)msg.obj),这是一个抽象的方法,我们需要重写这个方法,在方法中处理我们的任务。当任务完成时就会调用stopSelf()结束这个Service。
IntentService有以下特点:
(1) 它创建了一个独立的工作线程来处理所有的通过onStartCommand()传递给服务的intents。
(2) 创建了一个工作队列,来逐个发送intent给onHandleIntent()。
(3) 不需要主动调用stopSelft()来结束服务。因为,在所有的intent被处理完后,系统会自动关闭服务。
(4) 默认实现的onBind()返回null
(5) 默认实现的onStartCommand()的目的是将intent插入到工作队列中
在IntentService中有一个队列的概念,即在第一次启动IntentService,并在onHandleIntent中执行的时候,再第二次次启动IntentService,第二次的操作不会立刻执行,而是先将其放在队列中,当第一次运行完时,再执行第二次操作。这与Service是不一样的,当第一次还未执行完时,启动第二次,他会直接从onStartCommand开始执行。而不是像第一次一样按循序执行。
使用IntentService的好处:
会创建单独的线程处理onHandleIntent()方法,开发者不用处理多线程的问题;
onHandleIntent()执行完成后会自动调用stopSelf(),开发者不用自己调用;
为Service的onBind方法提供了默认实现(默认返回null),即不用重写onBind;
为onStartCommand提供了默认实现,即不用重写onStartCommand,该实现会将请求Intent添加到队列中。
只用重写onHandleIntent即可。 例子:public class MyIntentService extends IntentService {
final static String TAG="vic";
public MyIntentService() {
super("");
}
@Override
protected void onHandleIntent(Intent arg0) {//只用重写onHandleIntent这个抽象方法
Log.i(TAG,"begin onHandleIntent()");
try {
Thread.sleep(5*1000); //执行耗时任务
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i(TAG,"end onHandleIntent()");
}
}
启动这个IntentService的代码:
Intent intent=new Intent(this,MyIntentService.class);
startService(intent);
注意
:自定义的IntentService构造函数是必需要有,而且必须调用IntentService(字符串) ,因为工作线程的构造函数必须使用一个名称。