原创文章,转载请注意出处: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; }