【转】android service 之二(IntentService)

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

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

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

Java代码  

  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时,你必须提供一个无参构造函数,且在该构造函数内,你需要调用父类的构造函数,如下:

Java代码  

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

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

Java代码  

  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. }

Java代码  

  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内部起多个线程,但是这样的话,你可要处理好线程的同步哦~~~

时间: 2024-10-09 21:18:31

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

Android Service学习之IntentService 深入分析

什么是IntentService? (本文转自http://blog.csdn.net/gaojie314/archive/2010/11/28/6040701.aspx) 官方的解释是: IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through android.conten

android Service服务(二)

1.1 活动和服务进行通信 上一节中我们学习了启动和停止服务的方法.不知道你又没有发现,虽然服务是在活动里启动的,但在启动了服务之后,活动和服务基本上就没关系了,确实如此,我们在活动里调用了startService()方法来启动myService这个服务,然后MyService的onCreate()和onStartCommand()方法就会得到执行.之后服务一直处于运行状态,但具体运行的是什么逻辑,活动就控制不了了.这就类似于活动通知了服务一下:'你可以启动了!' 然后服务就去忙自己的事情了,但

Android Service(二)

上一篇文章中我们启动service的方法是: startService() intent = new Intent("android.startService");//区分服务类型 Bundle bundle = new Bundle(); bundle.putInt("op", op); intent.putExtras(bundle); startService(intent); //此处也可以用 intent.setClass(this,StartMusicS

Android学习笔记二十五.Service组件入门(三)使用IntentService

使用IntentService 1.Service缺陷 由于Service本身存在以下两个问题: (1)Service不会专门启动一条单独的进程,Service与他所在应用位于同一进程中: (2)Service也不是专门一条新的线程,如果我们在Service中直接处理耗时的任务,那么就会导致应用程序出现假性"卡死".如果我们需要在Service处理耗时任务,也可以在Service的onCreate()方法中启动一条新线程来处理该耗时任务(如上例).但是,问题来了,启动Service的A

Android Binder分析二:Natvie Service的注冊

这一章我们通过MediaPlayerService的注冊来说明怎样在Native层通过binder向ServiceManager注冊一个service,以及client怎样通过binder向ServiceManager获得一个service,并调用这个Service的方法. Native Service的注冊 这里以MediaPlayerService举例来说明怎样在Native层注冊Service,首先来看main_mediaservice.cpp的main方法: int main(int a

Android Service完全解析(二)

转载请注册出处:http://blog.csdn.net/guolin_blog/article/details/9797169 在上一篇文章中,我们学习了Android Service相关的许多重要内容,包括Service的基本用法.Service和Activity进行通信.Service的销毁方式.Service与Thread的关系.以及如何创建前台Service.以上所提到的这些知识点,基本上涵盖了大部分日常开发工作当中可能使用到的Service技术.不过关于Service其实还有一个更加

Android Service 服务(二)—— BroadcastReceiver

(转自:http://blog.csdn.net/ithomer/article/details/7365147) 一. BroadcastReceiver简介 BroadcastReceiver,用于异步接收广播Intent,广播Intent是通过调用Context.sendBroadcast()发送.BroadcastReceiver()接收. 广播Intent的发送是通过调用Context.sendBroadcast().Context.sendOrderedBroadcast().Con

Android Service不能再详细的教程

这篇包含了: Service后台服务.前台服务.IntentService.跨进程服务.无障碍服务.系统服务 几乎所有Android Service相关的东西. 前言 作为四大组件之一的Service类,是面试和笔试的必备关卡,我把我所学到的东西总结了一遍,相信你看了之后你会对Service娓娓道来,在以后遇到Service的问题胸有成竹,废话不多说,开车啦 Service是Android中实现程序后台运行的解决方案,它非常适用于去执行那些不需要和用户交互而且还要求长期运行的任务.Service

Android Service使用详解

Service是Android系统中的四大组件之一,主要有两个应用场景:后台运行和跨进程访问.Service可以在后台执行长时间运行操作而不提供用户界面,除非系统必须回收内存资源,否则系统不会停止或销毁服务.服务可由其他应用组件启动,而且即使用户切换到其他应用,服务仍将在后台继续运行. 此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC) 需要注意的是,Service是在主线程里执行操作的,可能会因为执行耗时操作而导致ANR 一.基础知识 Service可以分为以下三种形式