原文网址: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. WC2015流水账

    THU那四场考试没考好,只有20+名.这也许是我OI生涯中最后一场吧(已确认是最后一场),真是感慨万千. day0 搬进浙大宿舍404房间(神房间号),四个人一间.中午发现学军伙食相当良心,是我参加的 ...

  2. Binary Tree Zigzag Level Order Traversal (LeetCode) 层序遍历二叉树

    题目描述: Binary Tree Zigzag Level Order Traversal AC Rate: 399/1474 My Submissions Given a binary tree, ...

  3. nginx 配置自签名的ssl证书

    最近要搭一个https的测试环境,使用nginx做反向代理. 网上找过不少资料,但过程不是很完整,吃了不少亏,故把自己的操作过程总结下来.如果你刚好遇到这个问题,希望对你有帮助! ********** ...

  4. WP独立文件资源字典

    有时候,开发者想把资源字典定义在单独的XAML文件中,在网上找了找,没找到比较详细的,自己弄了许久. 1. 新建xaml资源字典文件,如在根目录下“ResourceDictionary1.xaml”, ...

  5. linux伪文件与proc文件

    linux/unix系统的文件类型大致可分为三类:普通文件.目录文件和伪文件.常见的伪文件分别是特殊文件.命名管道及proc文件. 伪文件不是用来存储数据的,因此这些文件不占用磁盘空间,尽管这些文件确 ...

  6. 自定义ViewGroup 流式布局

    使用 public class MainActivity extends Activity {     @Override     protected void onCreate(Bundle sav ...

  7. C#_Socket网络编程实现的简单局域网内即时聊天,发送文件,抖动窗口。

    最近接触了C#Socket网络编程,试着做了试试(*^__^*) 实现多个客户端和服务端互相发送消息 发送文件抖动窗口功能 服务端: using System; using System.Collec ...

  8. (三)一个工作任务引起的乱战——udp通信

    先上代码.该代码是在问度娘的过程中搜到的,自己实验运行了下,可以使用(vs2010  net fram4.0).服务端代码: using System;using System.Collections ...

  9. HTML与CSS入门——第六章 使用字体

    知识点: 1.粗体.斜体和特殊文本格式的使用 2.字体的调整方法 3.特殊字符的使用方法 6.1 粗体.斜体和特殊文本格式: font-weight控制粗细 加粗<strong> font ...

  10. iPhone手机的屏幕尺寸、分辨率及适配

    1.iPhone尺寸规格 设备 iPhone 宽 Width 高 Height 对角线 Diagonal 逻辑分辨率(point) Scale Factor 设备分辨率(pixel) PPI 3GS ...