原文网址: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. Spring容器的工具类

    代码实现: package com.ht.util; import java.util.Map; import org.springframework.beans.BeansException; im ...

  2. Demon_Tank (坦克移动发射子弹)

    using UnityEngine; using System.Collections; public class Tank : MonoBehaviour { //子弹预设体 public Game ...

  3. hibernate jpa 注解 @Temporal(TemporalType.DATE) 格式化时间日期,页面直接得到格式化类型的值

    1.日期: @Temporal(TemporalType.DATE) @Column(name = "applyDate", nullable = false, length = ...

  4. Android 中使用 html 作布局文件

    在Android开发中,通常使用xml格式来描述布局文件.就目前而言,熟悉android布局及美化的人员少之又少,出现了严重的断层.大部分企业,其实还是程序员自己动手布局.这样既浪费时间和精力,也未必 ...

  5. 解决Wamp 开启vhost localhost 提示 403 Forbbiden 的问题!

    非常奇怪的一个问题.我曾经从来都没有这样过!訪问 http://localhost/ 提示  403 Forbbiden. 我之前的设置一直都是这种: httpd.conf <Directory ...

  6. windows 7 SDK和DDK下载地址

    查个小资料,得到地址,顺便记录一下. Windows Driver Kit Version 7.1.0 http://www.microsoft.com/downloads/details.aspx? ...

  7. 获取布局 ActionBar

    LayoutInflater inflater = getLayoutInflater();View imageLayout = inflater.inflate(R.layout.preferenc ...

  8. CRT远程连接server字符输出乱码解决一例

    CRT远程连接server字符输出乱码解决一例 环境: server:Centos 6.2 远端:win 7 CRT版本号:7.1.1 现象回想: 1.server端:中文字符显示正常,例如以下: 2 ...

  9. java开发webservice的几种方式

    webservice的应用已经越来越广泛了,下面介绍几种在Java体系中开发webservice的方式,相当于做个记录. 1.Axis2 Axis是apache下一个开源的webservice开发组件 ...

  10. UltraEdit环境下,php简单环境配置

    1.语法高亮 菜单->视图->查看方式->选中“PHP” 2.自动补全 菜单->高级->配置->自动完成->选中“自动显示自动完成对话框”,字符数选择2-3为 ...