【转】android service 之二(IntentService)
原文网址:http://rainbow702.iteye.com/blog/1143286
不管是何种Service,它默认都是在应用程序的主线程(亦即UI线程)中运行的。所以,如果你的Service将要运行非常耗时或者可能被阻塞的操作时,你的应用程序将会被挂起,甚至会出现ANR错误。为了避免这一问题,你应该在Service中重新启动一个新的线程来进行这些操作。现有两种方法共大家参考:
① 直接在Service的onStartCommand()方法中重启一个线程来执行,如:
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- MyServiceActivity.updateLog(TAG + " ----> onStartCommand()");
- new Thread(new Runnable() {
- @Override
- public void run() {
- // 此处进行耗时的操作,这里只是简单地让线程睡眠了1s
- try {
- Thread.sleep(1000);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }).start();
- return START_STICKY;
- }
② 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
- Provides a default implementation of
onStartCommand()
that sends the intent to the work queue and then to youronHandleIntent()
implementation
提供了一个onStartCommand()方法的默认实现,它将Intent先传送至工作队列,然后从工作队列中每次取出一个传送至onHandleIntent()方法,在该方法中对Intent对相应的处理
以上,英文来自官方SDK,中文为我所译。
从以上看来,你所需要做的就是实现 onHandleIntent() 方法,在该方法内实现你想进行的操作。另外,继承IntentService时,你必须提供一个无参构造函数,且在该构造函数内,你需要调用父类的构造函数,如下:
- public HelloIntentService() {
- super("HelloIntentService");
- }
下面给出一例,来解释一下:
- // activity 的onCreate()
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- startSer1 = (Button) findViewById(R.id.startSer1);
- stopSer1 = (Button) findViewById(R.id.stopSer1);
- startSer2 = (Button) findViewById(R.id.startSer2);
- stopSer2 = (Button) findViewById(R.id.stopSer2);
- log = (TextView) findViewById(R.id.log);
- logView = (ScrollView) findViewById(R.id.logView);
- startSer1.setOnClickListener(btnListener);
- stopSer1.setOnClickListener(btnListener);
- startSer2.setOnClickListener(btnListener);
- stopSer2.setOnClickListener(btnListener);
- intent = new Intent(MyServiceActivity.this, IntentServiceDemo.class);
- // 打印出主线程的ID
- long id = Thread.currentThread().getId();
- updateLog(TAG + " ----> onCreate() in thread id: " + id);
- }
- // service 代码
- package com.archer.rainbow;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import android.app.IntentService;
- import android.content.Intent;
- public class IntentServiceDemo extends IntentService {
- private static final String TAG = "IntentServiceDemo";
- private static final SimpleDateFormat SDF_DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss.SSS");
- public IntentServiceDemo() {
- super(TAG);
- MyServiceActivity.updateLog(TAG + " ----> constructor");
- }
- @Override
- public void onCreate() {
- super.onCreate();
- // 打印出该Service所在线程的ID
- long id = Thread.currentThread().getId();
- MyServiceActivity.updateLog(TAG + " ----> onCreate() in thread id: "
- + id);
- }
- @Override
- public void onDestroy() {
- super.onDestroy();
- MyServiceActivity.updateLog(TAG + " ----> onDestroy()");
- }
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- MyServiceActivity.updateLog(TAG + " ----> onStartCommand()");
- // 记录发送此请求的时间
- intent.putExtra("time", System.currentTimeMillis());
- return super.onStartCommand(intent, flags, startId);
- }
- @Override
- public void setIntentRedelivery(boolean enabled) {
- MyServiceActivity.updateLog(TAG + " ----> setIntentRedelivery()");
- super.setIntentRedelivery(enabled);
- }
- @Override
- protected void onHandleIntent(Intent intent) {
- // 打印出处理intent所用的线程的ID
- long id = Thread.currentThread().getId();
- MyServiceActivity.updateLog(TAG
- + " ----> onHandleIntent() in thread id: " + id);
- long time = intent.getLongExtra("time", 0);
- Date date = new Date(time);
- try {
- // 打印出每个请求对应的触发时间
- MyServiceActivity.updateLog(TAG
- + " ----> onHandleIntent(): 下载文件中..." + SDF_DATE_FORMAT.format(date));
- Thread.sleep(3000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
应用启动时,界面如下:
从此图可以看出,主线程(UI线程)的ID是1。接,连续点击三次Start Service 1 按钮,得如下画面:
从此图中可以看出,IntentServiceDemo的onCreate()所处的线程ID仍为1,说明它是在主线程中被执行的,且只被执行一次。然后,我每点击一次按钮,它都会触发一下onStartCommand()方法。仔细看第二次与第三次的onCommand()方法以及onHandleIntent()打印出来的语句,你会发现,第二、三两次点击按钮与第一次点击按钮的时间是没有超过3秒钟的,它们是连续被执行的,这说明了什么呢?说明,在第一个intent被处理时(即onHandleIntent()处于运行中),该Service仍然可以接受新的请求,但接受到新的请求后并没有立即执行,而是将它们放入了工作队列中,等待被执行。
这就是 IntentService 的简单用法。但你若是想在Service中让多个线程并发的话,就得另想法子喽。比如,使用第一种方法,在Service内部起多个线程,但是这样的话,你可要处理好线程的同步哦~~~
【转】android service 之二(IntentService)的更多相关文章
- Android Service学习之IntentService 深入分析
什么是IntentService? (本文转自http://blog.csdn.net/gaojie314/archive/2010/11/28/6040701.aspx) 官方的解释是: ...
- android Service服务(二)
1.1 活动和服务进行通信 上一节中我们学习了启动和停止服务的方法.不知道你又没有发现,虽然服务是在活动里启动的,但在启动了服务之后,活动和服务基本上就没关系了,确实如此,我们在活动里调用了start ...
- Android Service总结03 之被启动的服务 -- Started Service
Android Service总结03 之被启动的服务 -- Started Service 版本 版本说明 发布时间 发布人 V1.0 添加了Service的介绍和示例 2013-03-17 Sky ...
- Android Service总结05 之IntentService
Android Service总结05 之IntentService 版本 版本说明 发布时间 发布人 V1.0 添加了IntentService的介绍和示例 2013-03-17 Skywang ...
- Android Service 服务(二)—— BroadcastReceiver
(转自:http://blog.csdn.net/ithomer/article/details/7365147) 一. BroadcastReceiver简介 BroadcastReceiver,用 ...
- Android Service不能再详细的教程
这篇包含了: Service后台服务.前台服务.IntentService.跨进程服务.无障碍服务.系统服务 几乎所有Android Service相关的东西. 前言 作为四大组件之一的Service ...
- Android 多线程之IntentService 完全详解
关联文章: Android 多线程之HandlerThread 完全详解 Android 多线程之IntentService 完全详解 android多线程-AsyncTask之工作原理深入解析(上) ...
- 从零开始学android -- Service
废话不多说了,Service是四大组件之一,是一个后台处理长时间运行在主线程不需要依赖ui界面显示的应用组件,切记不能在service中做耗时操作,会阻塞主线程,要做也要在service中开个子线程做 ...
- android service 的各种用法(IPC、AIDL)
http://my.oschina.net/mopidick/blog/132325 最近在学android service,感觉终于把service的各种使用场景和用到的技术整理得比较明白了,受益颇 ...
随机推荐
- 护肤品总结 Skin Care (2)
接护肤品总结(1) 面膜篇 个人不太喜欢片状面膜,所以用膏状面膜比较多. 1. Origins Drink Up-Intensive Overnight Mask 悦木之源补水睡眠面膜 牛油果油油的质 ...
- [置顶] 宏途_LCD调试流程.
今天在调试宏途的LCD屏时,开始是开机屏幕不亮,背光都不亮,可能板子已经损坏,一般通过测试电流电压简单验证,(注:硬件引脚没焊好也会引起读lcd id出现错误!!!)出现这个问题一般是因为引脚没焊好, ...
- EXP/IMP的三种模式
基本语法和实例: 1.EXP: 有三种主要的方式(完全.用户.表) 1.完全: EXP SYSTEM/MANAGER BUFFER=64000 FI ...
- SecureCRT7.3和SecureFX7.3的MAC下破解
破解脚本:http://files.cnblogs.com/files/jieyuefeng/SecureCRTFX_mac_crack.zip 破解方法: sudo perl ~/Downloads ...
- UNIX时间与本地时间的转换
所谓UNIX时间,维基百科的解释:UNIX时间,或称POSIX时间是UNIX或类UNIX系统使用的时间表示方式:从协调世界时1970年1月1日0时0分0秒起至现在的总秒数,不包括闰秒 知道了是什么,就 ...
- jquery easyui Tab 引入页面的问题
jQuery Easyui 的tabs插件有两种方式加载某个tab(标签页)上的内容:“href远程请求”和“content本地内容”,本文就两种方式的优缺点进行简单分析和思考. 两者特点: href ...
- C++中的四种转型操作符
在具体介绍C++中的四种转型操作符之前,我们先来说说旧式转型的缺点: ①它差点儿同意将不论什么类型转换为不论什么其它类型,这是十分拙劣的.假设每次转型都可以更精确地指明意图,则更好. ②旧式转型难以辨 ...
- C++ 推断进程是否存在
[cpp] view plaincopyprint? #include <windows.h> #include "psapi.h" #include"std ...
- [ES6] WeakMap vs Map
WeakMap: is a type of Map where only objects can be passed as keys. Primitive data type -- such are ...
- Android Fragment详解(二):Fragment创建及其生命周期
Fragments的生命周期 每一个fragments 都有自己的一套生命周期回调方法和处理自己的用户输入事件. 对应生命周期可参考下图: 创建片元(Creating a Fragment) To c ...