Android IntentService使用介绍以及原理分析

简介

  • 在Android应用的程序中,普通的Service中的代码是运行在主线程中的,如果想要在Service中做些耗时的操作,就很容易出现ANR的现象(大概是20秒),那么我们经常的做法就是,在onStartCommon方法中开启一个子线程然后内部执行耗时的操作,在执行完毕后如果需要自动停止服务需要在子线程的run方法中调用stopSelf()来停止服务。
  • 虽说在Service中执行耗时的代码可以很容易的实现,但是Android提供的IntentService类可以很方便的解决了自己开启线程和手动停止服务的问题。接下来看看IntentService的使用步骤。

使用步骤

  • IntentService是一个抽象类内部有一个抽象的方法 handleIntent(),继承至Service类.所以使用它需要继承它实现抽象方法。
      public class MyIntentService extends IntentService {
      private static final String TAG = "MyIntentService";
      public MyIntentService() {
          super("MyIntentService");
      }
    
      @Override
      protected void onHandleIntent(Intent intent) {
          //在这里通过intent携带的数据,开进行任务的操作。
          Log.d(TAG, "onHandleIntent: " + Thread.currentThread().getName());
      }
    
      @Override
      public void onDestroy() {
          super.onDestroy();
          Log.d(TAG, "onDestroy: ");
        }
    }
    
  • 然后调用StartService()启动异步后台服务类 IntentService。
      startService.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  Intent intent = new Intent(MainActivity.this, MyIntentService.class);
                  startService(intent);
              }
          });
    

源码分析

  • 服务启动的过程中,会去执行服务的生命周期方法,在开启服务的时候,有两种方式,分别为startService和bindService
  • startService方式启动,生命周期方法执行的顺序是 onCreate(),onStartCommand() onStart() onDestroy(),按照生命周期执行顺序我们查看IntentService的源码
   // onCreate方法的分析
    @Override
   public void onCreate() {
       super.onCreate();
       HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
       //创建了一个Looper对象 & MessageQueue对象 调用了Looper.loop方法
       thread.start();
       //   获取到HandlerThread中创建好的Looper对象。
       mServiceLooper = thread.getLooper();
       //ServiceHandler extends Handler,绑定了HandlerThread中的Looper对象 ;那个线程调用了Looper中的loop方法,Handler的dispatchMessage方法就运行在那个线程中。
       mServiceHandler = new ServiceHandler(mServiceLooper);
   }
 //onStartCommand()方法分析
  public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
       // 调用了onStart方法
       onStart(intent, startId);
       return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
   }
//onStart方法
public void onStart(@Nullable Intent intent, int startId) {
       //在这里构造了一个消息对象
       Message msg = mServiceHandler.obtainMessage();

       msg.arg1 = startId;
       //将intent 包装到了Message的obj中,
       msg.obj = intent;
       //然后调用sendMessage()将消息插入到队列中。
       //最终消息被取出然后被分发,最后调用了handleMessage()来处理这个消息
       mServiceHandler.sendMessage(msg);
   }
   //ServiceHandler handleMessage方法的分析
   private final class ServiceHandler extends Handler {
       public ServiceHandler(Looper looper) {
           super(looper);
       }

       @Override
       public void handleMessage(Message msg) {
           //SeriviceHandler 的handleMessage()方法中 将接受到的消息交给onHandleIntent来处理,onHandleIntent方法就是我们实现的方法,获取到Intent,处理任务。
           onHandleIntent((Intent) msg.obj);
           //执行完 结束服务
           stopSelf(msg.arg1);
       }
   }
  // onDestroy()方法的处理
  @Override
   public void onDestroy() {
       //将消息队列中的所有消息给移除,包括处理中的和未处理的
       mServiceLooper.quit();
   }

总结说来就是,开启服务执行onCreate()方法,方法中创建好了一个子线程(HandlerThread),(子线程中创建好了一个Looper对象同时创建好了一个MessagqQueue消息队列,然后开启轮询消息队列。),内部创建好的Handler与子线程中的Looper对象绑定。onCreate只有在服务第一次创建的时候才会调用,之后每次调用都只会执行onStartCommand方法,在此方法中我们构建好了一个Message对象,并且将传递进来的Intent封装在Mesage,一起发送到消息队列中。经过轮询将消息分发到Handler的handleMessage中处理,此时获取到Message中携带的Intent传递给我们实现好的handleIntent方法中进行任务的处理,处理完毕自动调用StopSlef来结束服务。在onDestroy方法会把所有消息都给退出。

  • 上文中我们分析了startService方法启动的服务,那bindService方式启动服务的分析如下(绑定服务,建立长期通信),bindService启动会执行 onCreate -> onBind -> onUnBind -> onDestroy方法。
 //onCreate方法上文中已经分析
 //onBind()
  public IBinder onBind(Intent intent) {
       //直接返回null了。那么不对会Mesage对象和发送消息到队列中,
       //然后回调handleIntent方法了。
       return null;
   }

所以bindService方式启动服务,不会进行多线程的操作。

问题记录

简单描述一下IntentService
  • IntentService是一个特殊的Service类,是实现了多线程处理异步请求的一个服务类,在handleIntent方法中进行耗时的操作,如果有多个耗时的操作任务,会按照顺序去一个一个的执行,执行完一个关闭一个。
在源码handleMessage方法中为什么执行完handleIntent方法会去调用带参数的stopSelf()
  • 因为stopSelf()的执行会立刻将服务停止掉,而带参数的stopSelf(int startId)会在所有任务执行完毕后将服务给停止。通常情况下调用stopSelf(int satrtId)方法不会立刻去执行停止服务的操作,会去判断最近执行任务的次数是否和startId相等,如果相等就立刻执行停止服务的操作。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • 闹铃响,关掉,清醒一两分钟,起床,上厕所,打开听书,绑上头发,做一套保健操,开始洗漱,慢慢往脸上擦着水乳液防晒,这...
    薇安妮阅读 227评论 0 0
  • 第五天,目标一塔县 今天,途经卡拉库里湖、慕士塔格峰、石头城、塔什库尔干县(塔县)。行程约300公里,...
    燕枫简书阅读 486评论 0 0
  • 刚认识c先生的时候,不觉得他怎么样,相貌平平还带着眼镜,身材也不高,但我却从他身上感觉到一种不一样的气息,...
    晴空蔚蓝阅读 196评论 0 1
  • 一朵花,我看到的是在暴风中挣扎后的绽放; 一颗水晶,我看到的是浑浊世界背后的眼睛; 一只小鸟,我...
    烽火煤阅读 242评论 0 0
  • 晚上爸爸下班回家了,坐在椅子上,一边休息,一边看报纸,我看见爸爸很累的样子,连忙倒了一杯水,说:爸爸喝口水吧,爸爸...
    敏敏_98f5阅读 83评论 0 0