原创文章,转载请注意出处:http://blog.csdn.net/ruils/article/details/17251935
IntentService是一个很有意思的类,它的实现可以看成是命令设计模式。
如果对android Handler,Looper模型熟悉的话, IntentService就很好理解了。
IntentService继承自Service,它把发过来的请求放在消息队列中,按照队列的顺序在HandlerThread中一个一个处理,处理完毕则把自己Stop掉。
IntentService的用法很简单,写一个继续它的子类,重写onHandleIntent方法,然后死命的start这个service就可以了。
下面一步一步分析:
1.IntentService启动时创建一个HandlerThread,并启动它,然后用这个HandlerThread的looper,创建一个ServiceHandler. onCreate在IntentService的生命周期中,只会调用一次。
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
2. 有新的命令请求过来,就会把这个Intent放在消息列队中。onStartCommand会在IntentService生命周期中调用一次或者多次。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
3. 所有发过来的请求都会发到这里来处理,至于怎么处理,就要自己重写onHandleIntent这个虚方法了。处理完之后就会调用 stopSelf(msg.arg1)这个方法,这里要注意,每处理完一个Intent就会Stop一次,但IntentService并不一定会被Stop掉,因为这个stop方法带有参数,只有消息队列中没有要处理的Intent了,IntentService才会真正stop掉。
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);
}
}
protected abstract void onHandleIntent(Intent intent);
4.结束的时候,退出消息循环。
@Override
public void onDestroy() {
mServiceLooper.quit();
}
最后,IntentService有Redelivery模式,默认是关闭的,打开Redelivery模式后,它能保证最后一次发送的Intent命令能被完全执行到,即使IntentService挂掉了,也会重启再执行。
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}