IntentService

本文深入解析了Android中的IntentService,一种用于处理异步请求的服务组件。它内部利用HandlerThread和Handler机制,确保所有Intent以串行方式处理,避免了主线程阻塞。文章详细介绍了IntentService的启动流程、消息队列机制及为何适合处理耗时操作。

IntentService是继承Service的抽象类,所以IntentService的实现类需要重写onHandleIntent()方法。

内部:HandlerThread + Handler

 

HandlerThread

它是android提供的一个方便、便捷的类,用于快速创建一个带有Looper的线程。Looper可以用来创建Handler实例。注意:start()仍然必须被调用。

 

private void initHandlerThread(){
    //创建HandlerThread实例
    mHandlerThread = new HandlerThread("handler_thread");
    //开始运行线程
    mHandlerThread.start();
    //获取HandlerThread线程中的Looper
    Looper loop = mHandlerThread.getLooper();
    //创建Handler与该线程绑定
    mSubThreadHandler = new Handler(loop){};
}

看看IntentService的源码:

package android.app;

import android.annotation.WorkerThread;
import android.annotation.Nullable;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;

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

    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     */
    public IntentService(String name) {
        super();
        mName = name;
    }

    /**
     * Sets intent redelivery preferences.  Usually called from the constructor
     */
    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

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

    @Override
    public void onStart(@Nullable 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
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

    /**
     * Unless you provide binding for your service, you don't need to implement this
     */
    @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }

    /**
     */
    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}

从源码可以看出,在执行onCreate方法时会创建一个HandlerThread对象,并启动线程。紧接着创建ServiceHandler对象, ServiceHandler继承自Handler,用来处理消息。ServiceHandler将获取HandlerThread的Looper就可以开始工作了。

每启动一次onStart方法,就会把消息 和 数据 发给 mServiceHandler,相当于发送了一个Message 给 HandlerThread的消息队列。mServiceHandler会把 数据 传给 onHandleIntent方法, onHandleIntent是个抽象方法,需要在IntentService子类实现,每次onStart之后都会调用onHandleIntent方法去处理。处理完毕后,会调用stopSelf通知HandlerThread已经处理完毕,HandlerThread继续观察消息队列,如果还有未执行的message则继续执行,否则结束。

 

启动IntentService为什么不需要新建线程?

IntentService内部的HandlerThread继承自Thread,内部封装了Looper,在这里新建线程并启动,所以启动IntentService不需要新建线程。

为什么不建议通过 bindService 方法启动 IntentService?

    @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }

IntentService源码中的onBind方法默认返回 null;不适合使用bindService启动。当然,如果执意要使用 bindService方法启动 IntentService,可能是想通过 Binder 或 Messenger 使IntentService 和 Activity可以通信, 这样的情况下 onHandleIntent不会被回调,相当于是在使用Service而不是IntentService。

 

为什么多次启动 IntentService 会顺序执行事件,停止服务后,后续的事件得不到执行?(也可以说IntentService中的操作不能被打断)

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

@Override
public void onDestroy() {
    mServiceLooper.quit();
}

IntentService中使用Handler、Looper、MessageQueue机制把消息发送到线程中去执行, 所以多次启动 IntentService不会重新创建新的服务 和 新的 线程,只是把消息 加入消息队列中等待执行, 而如果服务停止,会清除消息队列中的消息----mServiceLooper.quit();,后续的事件得不到执行。

 

IntentService特点:

1)IntentService是继承自Service并处理异步请求的类, 在其内部创建了一个独立的工作线程来处理所有通过onStartCommand传递给服务的intent;

2)创建了一个工作队列,来逐个发送intent 给 onHandleIntent处理;

3)当任务执行完以后, IntentService自动停止,因为内部调用了stopSelf方法,所以不需要我们手动结束;

4)onBind方法默认返回null

注:如果启动 IntentService多次,那么每一个耗时操作会以工作队列的方式在 IntentService 的onHandleIntent 回调中执行,依次去执行, 使用串行的方式,执行完自动结束。

 

Service

    Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,不建议在Service中编写耗时操作,否则会引起ANR,为了解决这样的问题,引入了IntentService。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值