原文网址:http://rainbow702.iteye.com/blog/1143286

不管是何种Service,它默认都是在应用程序的主线程(亦即UI线程)中运行的。所以,如果你的Service将要运行非常耗时或者可能被阻塞的操作时,你的应用程序将会被挂起,甚至会出现ANR错误。为了避免这一问题,你应该在Service中重新启动一个新的线程来进行这些操作。现有两种方法共大家参考:

① 直接在Service的onStartCommand()方法中重启一个线程来执行,如:

  1. @Override
  2. public int onStartCommand(Intent intent, int flags, int startId) {
  3. MyServiceActivity.updateLog(TAG + " ----> onStartCommand()");
  4. new Thread(new Runnable() {
  5. @Override
  6. public void run() {
  7. // 此处进行耗时的操作,这里只是简单地让线程睡眠了1s
  8. try {
  9. Thread.sleep(1000);
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. }
  14. }).start();
  15. return START_STICKY;
  16. }

② Android SDK 中为我们提供了一个现成的Service类来实现这个功能,它就是IntentService,它主要负责以下几个方面:

  • Creates a default worker thread that executes all intents delivered to onStartCommand() separate from your application's main thread.

生成一个默认的且与主线程互相独立的工作者线程来执行所有传送至 onStartCommand() 方法的Intetnt

  • Creates a work queue that passes one intent at a time to your onHandleIntent() implementation, so you never have to worry about multi-threading.

生成一个工作队列来传送Intent对象给你的onHandleIntent()方法,同一时刻只传送一个Intent对象,这样一来,你就不必担心多线程的问题。

  • Stops the service after all start requests have been handled, so you never have to call stopSelf().

在所有的请求(Intent)都被执行完以后会自动停止服务,所以,你不需要自己去调用stopSelf()方法来停止该服务

  • Provides default implementation of onBind() that returns null.

提供了一个onBind()方法的默认实现,它返回null

提供了一个onStartCommand()方法的默认实现,它将Intent先传送至工作队列,然后从工作队列中每次取出一个传送至onHandleIntent()方法,在该方法中对Intent对相应的处理

以上,英文来自官方SDK,中文为我所译。

从以上看来,你所需要做的就是实现 onHandleIntent() 方法,在该方法内实现你想进行的操作。另外,继承IntentService时,你必须提供一个无参构造函数,且在该构造函数内,你需要调用父类的构造函数,如下:

  1. public HelloIntentService() {
  2. super("HelloIntentService");
  3. }

下面给出一例,来解释一下:

  1. // activity 的onCreate()
  2. @Override
  3. public void onCreate(Bundle savedInstanceState) {
  4. super.onCreate(savedInstanceState);
  5. setContentView(R.layout.main);
  6. startSer1 = (Button) findViewById(R.id.startSer1);
  7. stopSer1 = (Button) findViewById(R.id.stopSer1);
  8. startSer2 = (Button) findViewById(R.id.startSer2);
  9. stopSer2 = (Button) findViewById(R.id.stopSer2);
  10. log = (TextView) findViewById(R.id.log);
  11. logView = (ScrollView) findViewById(R.id.logView);
  12. startSer1.setOnClickListener(btnListener);
  13. stopSer1.setOnClickListener(btnListener);
  14. startSer2.setOnClickListener(btnListener);
  15. stopSer2.setOnClickListener(btnListener);
  16. intent = new Intent(MyServiceActivity.this, IntentServiceDemo.class);
  17. // 打印出主线程的ID
  18. long id = Thread.currentThread().getId();
  19. updateLog(TAG + " ----> onCreate() in thread id: " + id);
  20. }
  1. // service 代码
  2. package com.archer.rainbow;
  3. import java.text.SimpleDateFormat;
  4. import java.util.Date;
  5. import android.app.IntentService;
  6. import android.content.Intent;
  7. public class IntentServiceDemo extends IntentService {
  8. private static final String TAG = "IntentServiceDemo";
  9. private static final SimpleDateFormat SDF_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss.SSS");
  10. public IntentServiceDemo() {
  11. super(TAG);
  12. MyServiceActivity.updateLog(TAG + " ----> constructor");
  13. }
  14. @Override
  15. public void onCreate() {
  16. super.onCreate();
  17. // 打印出该Service所在线程的ID
  18. long id = Thread.currentThread().getId();
  19. MyServiceActivity.updateLog(TAG + " ----> onCreate() in thread id: "
  20. + id);
  21. }
  22. @Override
  23. public void onDestroy() {
  24. super.onDestroy();
  25. MyServiceActivity.updateLog(TAG + " ----> onDestroy()");
  26. }
  27. @Override
  28. public int onStartCommand(Intent intent, int flags, int startId) {
  29. MyServiceActivity.updateLog(TAG + " ----> onStartCommand()");
  30. // 记录发送此请求的时间
  31. intent.putExtra("time", System.currentTimeMillis());
  32. return super.onStartCommand(intent, flags, startId);
  33. }
  34. @Override
  35. public void setIntentRedelivery(boolean enabled) {
  36. MyServiceActivity.updateLog(TAG + " ----> setIntentRedelivery()");
  37. super.setIntentRedelivery(enabled);
  38. }
  39. @Override
  40. protected void onHandleIntent(Intent intent) {
  41. // 打印出处理intent所用的线程的ID
  42. long id = Thread.currentThread().getId();
  43. MyServiceActivity.updateLog(TAG
  44. + " ----> onHandleIntent() in thread id: " + id);
  45. long time = intent.getLongExtra("time", 0);
  46. Date date = new Date(time);
  47. try {
  48. // 打印出每个请求对应的触发时间
  49. MyServiceActivity.updateLog(TAG
  50. + " ----> onHandleIntent(): 下载文件中..." + SDF_DATE_FORMAT.format(date));
  51. Thread.sleep(3000);
  52. } catch (InterruptedException e) {
  53. e.printStackTrace();
  54. }
  55. }
  56. }

应用启动时,界面如下:


 从此图可以看出,主线程(UI线程)的ID是1。接,连续点击三次Start Service 1 按钮,得如下画面:

从此图中可以看出,IntentServiceDemo的onCreate()所处的线程ID仍为1,说明它是在主线程中被执行的,且只被执行一次。然后,我每点击一次按钮,它都会触发一下onStartCommand()方法。仔细看第二次与第三次的onCommand()方法以及onHandleIntent()打印出来的语句,你会发现,第二、三两次点击按钮与第一次点击按钮的时间是没有超过3秒钟的,它们是连续被执行的,这说明了什么呢?说明,在第一个intent被处理时(即onHandleIntent()处于运行中),该Service仍然可以接受新的请求,但接受到新的请求后并没有立即执行,而是将它们放入了工作队列中,等待被执行。

这就是 IntentService 的简单用法。但你若是想在Service中让多个线程并发的话,就得另想法子喽。比如,使用第一种方法,在Service内部起多个线程,但是这样的话,你可要处理好线程的同步哦~~~

【转】android service 之二(IntentService)的更多相关文章

  1. Android Service学习之IntentService 深入分析

          什么是IntentService? (本文转自http://blog.csdn.net/gaojie314/archive/2010/11/28/6040701.aspx) 官方的解释是: ...

  2. android Service服务(二)

    1.1 活动和服务进行通信 上一节中我们学习了启动和停止服务的方法.不知道你又没有发现,虽然服务是在活动里启动的,但在启动了服务之后,活动和服务基本上就没关系了,确实如此,我们在活动里调用了start ...

  3. Android Service总结03 之被启动的服务 -- Started Service

    Android Service总结03 之被启动的服务 -- Started Service 版本 版本说明 发布时间 发布人 V1.0 添加了Service的介绍和示例 2013-03-17 Sky ...

  4. Android Service总结05 之IntentService

    Android Service总结05 之IntentService   版本 版本说明 发布时间 发布人 V1.0 添加了IntentService的介绍和示例 2013-03-17 Skywang ...

  5. Android Service 服务(二)—— BroadcastReceiver

    (转自:http://blog.csdn.net/ithomer/article/details/7365147) 一. BroadcastReceiver简介 BroadcastReceiver,用 ...

  6. Android Service不能再详细的教程

    这篇包含了: Service后台服务.前台服务.IntentService.跨进程服务.无障碍服务.系统服务 几乎所有Android Service相关的东西. 前言 作为四大组件之一的Service ...

  7. Android 多线程之IntentService 完全详解

    关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...

  8. 从零开始学android -- Service

    废话不多说了,Service是四大组件之一,是一个后台处理长时间运行在主线程不需要依赖ui界面显示的应用组件,切记不能在service中做耗时操作,会阻塞主线程,要做也要在service中开个子线程做 ...

  9. android service 的各种用法(IPC、AIDL)

    http://my.oschina.net/mopidick/blog/132325 最近在学android service,感觉终于把service的各种使用场景和用到的技术整理得比较明白了,受益颇 ...

随机推荐

  1. 护肤品总结 Skin Care (1)

    很久没有更博了,最近过年在家,就写些生活上面的总结吧- 从护肤品开始,接下来陆陆续续会有化妆品,北美生活购物等. 因为是学生党,所以此帖中的东西基本都是价钱适中.因为经常买买买,所以用的好的坏的都会在 ...

  2. [LeetCode] 134. Gas Station 解题思路

    There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. You ...

  3. 回调函数的意义以及python实现

    因工作需要,最近在学习使用python来解析各种文件,包括xmind,xml,excel,csv等等. 在学习python解析XML的时候看到这样一段话: 3.ElementTree(元素树) Ele ...

  4. zookeeper[6] zookeeper FAQ(转)

    转自:http://www.cnblogs.com/zhengran/p/4601855.html 1. 如何处理CONNECTION_LOSS?在Zookeeper中,服务器和客户端之间维持一个长连 ...

  5. Myeclipse中java文件注释格式设置

    点击菜单windows->preferences,然后在左侧栏选择java ->Code Style -> CodeTemplates然后在右侧栏选择comments -> 依 ...

  6. HDU 4099 Revenge of Fibonacci (数学+字典数)

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4099 这个题目就是一个坑或. 题意:给你不超过40的一串数字,问你这串数字是Fibonacci多少的开头 ...

  7. android离线下载的相关知识

    离线下载的功能点如下:      1.下载管理(开始.取消下载).      2.网络判断(Wi-Fi,3G).      3.独立进程.      4.定时和手机催醒.      5.自启动. 选择 ...

  8. Archlinux 从 AUR 源中安装应用

    Archlinux 从 AUR 源中安装应用 AUR((Arch 用户软件仓库) Arch用户软件仓库( Arch User Repository,AUR )是为用户而建.由用户主导的Arch软件仓库 ...

  9. DataGrid( 数据表格) 组件[4]

    本节课重点了解 EasyUI 中 DataGrid(数据表格)组件的使用方法,这个组件依赖于Panel(面板).Resizeable(调整大小).LinkButton(按钮).Pageination( ...

  10. CSS 特殊样式设置集合

    1. 父窗口宽度不定,要求内部两个子块, 第一个子块宽度固定,第二个子块宽度自适应. 第一个子块宽度固定,定位为绝对定位 position:absolute;  第二个子块设置margin-left即 ...