IntentService源码分析

  • IntentService是android为我们提供的一个Async的Service,其父类是Service,运行在一个单独的线程。可以顺序执行多个任务,执行完任务之后自动的调用stopSelf方法来停止服务
  • IntentService的优点异步顺序执行多个任务(通过Looper的MessageQueque管理) 执行任务完成之后自动停止 ,而普通的Service 运行在ui线程 如果开启多个线程下载的话,无法控制顺序 而且运行完成之后 不会自动停止 得用户手动判断 容易泄漏内存

  • 现在我们从源码的角度分析一下IntentService的工作流程

     public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
    
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }
    
  • 其在onCreate中完成了上面功能呢个,创建了一个HandlerThread,之后启动了Handler,又在HanlderThread中拿到了子线程的Looper,并通过子线程的Looper创建了一个ServiceHanlder

  • 我们先来看一下ServiceHanlder是什么?
private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            // 运行在子线程 因为拿的的是HandlerThread的looper
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
            // 不是说调用stopSelfservice就会停止 判断执行次数和startId是否一致  一致的话 就停止
        }
    }
  • 发现ServiceHanlder其实就是一个Handler,这里在Hanlder中的HanldeMessage方法中调用了OnHandleIntent方法(也就是子类实现的方法
  • 我们可以看到ServiceHandler中的Looper是HandlerThread的Looper,也就是子线程的Looper,我们的Handler的handleMessage方法运行在哪一个线程,不是Hanlder在哪一个线程中创建的handleMessage就运行在哪一个线程,而是有Looper所在的线程决定,handleMessage运行在哪一个线程
  • 接下来我们看一下HandleThread源码
  @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
  • 其核心代码是run方法,也就 是在run中给ThreadLocal存储了一个Looper,那么我们的ServiceHanlder也就可以直接拿到HandleThread的Looper,也就是直接运行在HandlerThread所在的线程
  • 我们知道,当我们startService的时候,service的生命周期是这样的
  • onCreate–>onStart onStart可以执行多次,我们的onStart源码是什么呢?
  @Override
    public void onStart(Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
  • 我们发现 onStart其实是将Intent和startId封装成了一个Message,之后交给了ServiceHandler处理,而我们的ServiceHanlder中的Looper是子线程HanlderThread的Looper,因此ServiceHanlder的handleMessage方法运行在子线程,因此可以在这里进行Async操作
  • 而handleMessage方法干什么呢?

    public void handleMessage(Message msg) {

        onHandleIntent((Intent)msg.obj);
        stopSelf(msg.arg1);
    }
    
  • 原来在handleMessage方法中回调了子类的onHandleIntent方法,那么我们的onHandleIntent也就运行在子线程中

  • 之后就是stopSelf() 这里不是说调用了stopSelf service就结束,而是判断了startid是否和启动次数相等,如果相等的话 才结束
  • stopSelf源码
public final void stopSelf(int startId) {
        if (mActivityManager == null) {
            return;
        }
        try {
            mActivityManager.stopServiceToken(
                    new ComponentName(this, mClassName), mToken, startId);
        } catch (RemoteException ex) {
        }
    }
  • 我们每启动同一个service,startId就加1,如果启动10次的话,那么startId为10,而对应每一个Intent传递过来的是从1–10,只有最后一个intent任务执行完了之后,才会结束服务
  • 这里之所以说IntentService是按照队列执行的原因是:在onStart中,ServiceHandler调用的是handleMessage()方法,没有发送延迟或者插入队列
  • 下面是一张原理图
  • 这里写图片描述
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值