关于HandlerThread和IntentService

HandlerThread和IntentService放在一起一方面是因为这两个东西都只有一丢丢东西,另一方面两个还有点关系。

HandlerThread

其实就是个Thread,然后内部给你创建了Looper和MessageQueue,然后暴露一个接口给外部,让外部能拿到内部的looper,然后创建Handler往线程里面发消息。

我的感觉就是简化版的主线程,但是同样的也不适合做长时间任务,原因类似主线程,都是单个线程通过looper实现循环操作,MessageQueue可能会存储多个Message待处理,所以你单个事件处理事件过长就会导致其他事件处理延后(主线程里面这样就会出现ANR),有时候就会达不到预期的效果。

给我的感觉HandlerThread的作用就是分担主线程的压力,把一些稍微耗时的操作放到子线程操作。实际上就是个单线程版的线程池。

核心源码一看其实就知道很简单,没啥好说的:

public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;
    private @Nullable Handler mHandler;
    ....
    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
    ....
}

IntentService

其实就是个Service,内部封装了一个HandlerThread,用来执行耗时操作,毕竟Service里面也不能执行耗时操作,所以开了一个线程来执行耗时操作,然后在线程执行完成的时候就会调用stopSelf停止掉Service,这也就是intentService相比较于普通Service的一个特点:不需要手动停止,任务执行完就会自动停止。

源码如下:

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

    @Override
    public void onCreate() {
        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);
    }

    @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();
    }
    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}

这个源码很少,内容比较清晰,onCreat里面初始化线程和Handler,onStart里面发送Message,然后onHandleIntent是实际的处理方法需要实现,处理完之后会调用停止服务,然后会调用Looper的不安全退出。

问题!!!:

我们可以看到实际上onStartCommand是可以多次调用的,即可以发送多个Message,理论上来说应该是Handler处理完所有Message才停止,但是实际上handleMessage中处理完一个Message就会停止服务及Looper,万一在处理的过程中收到第二个Message,然后只处理完第一个就停止了,那么我的第二个Message怎么办?那么多次onStartCommand又有什么用呢?

2018年9月7日 19:21:49

问题解答

正在等饭煮好呢,结果翻到任玉刚大神的Android开发艺术探索这本书上有关于HandlerThread和IntentService的内容,就想着复习一下,然后就发现了上面这个问题的答案,404页原文:“这里之所以采用stopSelf(int startId)而不是stopSelf()来停止服务,那是因为stopSelf()会立刻停止服务,而这个时候可能还有其他消息未处理,stopSelf(int startId)在尝试停止服务之前会判断最近启动服务的次数是否和startId相等,如果相等就立刻停止服务,不相等则不停止服务,这个策略可以从AMS的stopServiceToken方法的实现中找到依据。。。”,果然还是太年轻,学习的太少,加油!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值