IntentService的使用方法和原理

IntentService继承了Service,它是一个抽象类,用于执行后台的耗时任务,当任务结束后它会自动停止。由于IntentService是服务,所以它的优先级比普通的线程要高很多,所以它适合执行一些高优先级的后台任务。

当使用IntentService时,我们需实现onHandleIntent(Intent intent)方法,在里面就可以执行后台任务,比如下载、访问数据库、IO操作等。无需复写onCreate、onStartCommand、onStart等方法,只需实现onHandleIntent。

为什么onHandleIntent里面可以执行耗时操作?

IntentService封装了一个HandlerThread和一个ServiceHandler。当它第一次被启动时,onCreate方法会被调用:

@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);
}

这样通过ServiceHandler发送的消息最终都会在HandlerThread里执行(这是HandlerThread的特性),而ServiceHandler接收到消息后会去调用onHandleIntent,所以onHandleIntent可以执行耗时操作。

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);
    }
}

同时从上述源码可以看出,每当onHandleIntent执行结束后,IntentService会调用stopSelf(int startId)来尝试停止服务,为什么不采用stopSelf()而是采用stopSelf(int startId)呢?因为stopSelf()会立刻停止服务,而这个时候可能还有其他消息未处理;stopSelf(int startId)则会等待所有的消息都处理完毕后才终止服务。一般来说,stopSelf(int startId)在尝试停止服务前会判断最近启动服务的次数是否和startId相等,如果相等就立刻停止服务,不相等则不停止服务。每执行一个后台任务就必须要启动一次IntentService,它的onStartCommand会去调用onStart,然后通过发消息向HandlerThread请求执行任务,而Handler中的Looper是顺序处理消息的,所以IntentService会顺序执行后台任务。

@Override
public void onStart(Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

/**
 * You should not override this method for your IntentService. Instead,
 * override {@link #onHandleIntent}, which the system calls when the IntentService
 * receives a start request.
 * @see android.app.Service#onStartCommand
 */
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值