原文网址: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. 【转】C++动态创建二维数组,二维数组指针

    原作者博客:蒋国宝的IT技术博客 今天完成一道题目需要自己用指针创建一个二维的数组,不得不承认指针的确是恶心. int **result; ; ; result = new int*[row]; ; ...

  2. openstack neutron debugs lists

  3. solr安装

    Windows solr(tomcat) 1.1. 安装步骤 1.1.1准备工作 1. 服务器:apache-tomcat-7.0.40压缩版,http://localhost:8080/安装是否成功 ...

  4. CentOS 6.3下Samba服务器的安装与配置(转)

    CentOS 6.3下Samba服务器的安装与配置   一.简介 Samba是一个能让Linux系统应用Microsoft网络通讯协议的软件,而SMB是Server Message Block的缩写, ...

  5. Android中设置文本颜色的三种方法

    最近刚开始学web,发现好的颜色搭配可以让自己的网页更加美观, 中午不想做事,就无聊滴花了两个小时测试了所有颜色的编码,总结如下 新手没有什么吊炸天的技术,仅仅是一份辅助的文档,有兴趣的朋友可以收藏下 ...

  6. UIView层次管理bringSubviewToFront,sendSubviewToBack

    将一个UIView显示在最前面只需要调用其父视图的 bringSubviewToFront()方法. 将一个UIView层推送到背后只需要调用其父视图的 sendSubviewToBack()方法. ...

  7. Java基础知识强化55:经典排序之归并排序(MergeSort)

    1. 归并排序的原理: 原理,把原始数组分成若干子数组,对每一个子数组进行排序, 继续把子数组与子数组合并,合并后仍然有序,直到全部合并完,形成有序的数组 举例: 无序数组[6 2 4 1 5 9] ...

  8. [A Top-Down Approach][第二章 应用层]

    [A Top-Down Approach][第二章 应用层] 标签(空格分隔): 未分类 网络应用是计算机网络存在的理由 首先从定义几个关键的应用层概念开始 应用程序所需要的网络服务,客户和服务器,进 ...

  9. AnkhSVN 中文版 支持VS2015

    简介:AnkhSVN是一款在VS中管理Subversion的插件,您可以在VS中轻松的提交.更新.添加文件,而不用在命令行或资源管理器中提交,而且该插件属于开源项目. 这个版本是简体中文的重新编译版本 ...

  10. 1:scrapy框架原理与环境搭设

    1:原理图: (*此图来自网络) 2:开发过程: 1)编写items.py,确定要抓取的关键字段名称 2)编写spider,确定发送request的形式以及对于response的处理 3)编写pipe ...