并发编程(7)Intentservice源码分析

概述

前面分析了HandlerThread源码,下面按照顺序分析IntentService的源码,IntentService是自己维护了一个线程,来执行耗时的操作,然后里面封装了HandlerThread,能够方便在子线程创建Handler。

正文

注释

IntentService is a base class for {@link Service}s that handle asynchronous
requests (expressed as {@link Intent}s) on demand.  Clients send requests
through {@link android.content.Context#startService(Intent)} calls; the
service is started as needed, handles each Intent in turn using a worker
thread, and stops itself when it runs out of work.

IntentService是继承自Service用来处理异步请求的一个基类,客户端startService发送请求,IntentService就被启动,然后会在一个工作线程中处理传递过来的Intent,当任务结束后就会自动停止服务。

This "work queue processor" pattern is commonly used to offload tasks
from an application's main thread.  The IntentService class exists to
simplify this pattern and take care of the mechanics.  To use it, extend
IntentService and implement {@link #onHandleIntent(Intent)}.  IntentService
will receive the Intents, launch a worker thread, and stop the service as appropriate

工作器处理模式通常用来加载应用主线程的耗时任务,IntentService用来简化这种模式并且专注于耗时任务的处理。使用IntentService,需要继承IntentService并且复写onHandleIntent方法。IntentService在接收到一系列Intent之后,启动一个子线程,然后合适的实际关闭Service。

All requests are handled on a single worker thread -- they may take as
  long as necessary (and will not block the application's main loop), but
  only one request will be processed at a time.

所有的请求都是都是在同一个子线程中进行处理的—他们可能会花费很长时间(并不会阻塞应用的loop线程),但是在同一时刻IntentService只能处理一个请求。

通过注释,已经将IntentService的使用方式,使用场景描述地相当清楚,不再多解释,相比较我们自己在Intent中开启线程处理耗时任务,IntentService不需要我们自己去关闭Service,它自己会在任务完成之后自行关闭,不过每次只能处理一个任务,所以不适用于高并发,适用于请求数较少的情况,类似于APP的版本检测更新,后台定位功能以及读取少量的IO操作。

成员变量

    private volatile Looper mServiceLooper;//子线程中的Looper
    private volatile ServiceHandler mServiceHandler;//内部持有的一个Handler
    private String mName;//内部创建的线程名字
    private boolean mRedelivery;//服务被异常终止后重新创建调用onStartCommand是否回传Intent

ServiceHandler

  private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
          //子线程中回调Intent
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

内部创建了一个ServiceHandler,然后将传递过来的Intent封装成一个Message,然后再将Message封装成一个Intent,回调onHandleIntent,其实转换的目的就是讲主线程的Intent切换到子线程中去执行了而已。

构造方法

  //工作线程的名字
  public IntentService(String name) {
        super();
        mName = name;
    }

onCreate

    @Override
    public void onCreate() {
        super.onCreate();
        //创建HandlerThread   
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        //开启线程创建子线程Looper
        thread.start();
        //获取子线程Looper
        mServiceLooper = thread.getLooper();
       //创建子线程Handler
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

onStartCommand

  @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        //调用onStart方法
        onStart(intent, startId);
       //根据mRedelivery的值来确定返回重传Intent的黏性广播还是非黏性广播
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

onStart

  @Override
    public void onStart(@Nullable Intent intent, int startId) {
        //创建一个Message
        Message msg = mServiceHandler.obtainMessage();
        //消息标志,作为当前Service的标志
        msg.arg1 = startId;
        //携带Intent
        msg.obj = intent;
        //发送消息,此时将线程切换到子线程
        mServiceHandler.sendMessage(msg);
    }


   @Override
        public void handleMessage(Message msg) {
            //处理发送过来的消息,在子线程
            onHandleIntent((Intent)msg.obj);
           //处理完消息之后停止Service
            stopSelf(msg.arg1);
        }

onDestroy

    @Override
    public void onDestroy() {
       //退出Looper
        mServiceLooper.quit();
    }

使用方式

IntentService intentService = new IntentService("main") {
    @Override
    protected void onHandleIntent(Intent intent) {
        // 处理耗时操作
    }
};
//不需要关注Service的生命周期,IntentService会自行处理

总结

IntentService实际上内部实例化了一个HandlerThread,并且封装了一个Handler,所以他的工作流程通过上面的源码,分析如下:

  1. 创建一个HandlerThread,开启HandlerThread来创建Looper
  2. 创建一个Handler,传入Looper,从而在子线程实例化Handler
  3. 在onStartCommand中获取到的Intent作为消息的obj发送出去
  4. 然后在onHandleIntent中处理这个消息,注意此时是在子线程
  5. 跟HandlerThread一样,IntentService内部是采用Handler来实现的,所以任务是串行执行的,不适用于大量耗时操作。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269