9.5.2 使用 IntentService

话说回来,在本章一开始的时候我们就已经知道,服务中的代码都是默认运行在主线程 当中的,如果直接在服务里去处理一些耗时的逻辑,就很容易出现 ANR(Application Not Responding)的情况。
所以这个时候就需要用到 Android 多线程编程的技术了,我们应该在服务的每个具体的 方法里开启一个子线程,然后在这里去处理那些耗时的逻辑。因此,一个比较标准的服务就 可以写成如下形式:

public class MyService extends Service {

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
// 处理具体的逻辑
}
}).start();
return super.onStartCommand(intent, flags, startId);
}

}
但是,这种服务一旦启动之后,就会一直处于运行状态,必须调用 stopService()或者 stopSelf()方法才能让服务停止下来。所以,如果想要实现让一个服务在执行完毕后自动停止 的功能,就可以这样写:

public class MyService extends Service {

@Override
public IBinder onBind(Intent intent) {
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread(new Runnable() {
@Override
public void run() {
// 处理具体的逻辑
stopSelf();
}
}).start();
return super.onStartCommand(intent, flags, startId);
}

}
虽说这种写法并不复杂,但是总会有一些程序员忘记开启线程,或者忘记调用 stopSelf() 方法。为了可以简单地创建一个异步的、会自动停止的服务,Android 专门提供了一个 IntentService 类,这个类就很好地解决了前面所提到的两种尴尬,下面我们就来看一下它的 用法。
新建一个 MyIntentService 类继承自 IntentService,代码如下所示:

public class MyIntentService extends IntentService {

public MyIntentService() {
super("MyIntentService"); // 调用父类的有参构造函数
}

@Override
protected void onHandleIntent(Intent intent) {
// 打印当前线程的id
Log.d("MyIntentService", "Thread id is " + Thread.currentThread(). getId());
}

@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyIntentService", "onDestroy executed");
}

}

这里首先是要提供一个无参的构造函数,并且必须在其内部调用父类的有参构造函数。
然后要在子类中去实现 onHandleIntent()这个抽象方法,在这个方法中可以去处理一些具体的 逻辑,而且不用担心 ANR 的问题,因为这个方法已经是在子线程中运行的了。这里为了证 实一下,我们在 onHandleIntent()方法中打印了当前线程的 id。另外根据 IntentService 的特性, 这个服务在运行结束后应该是会自动停止的,所以我们又重写了 onDestroy()方法,在这里也 打印了一行日志,以证实服务是不是停止掉了。
接下来修改 activity_main.xml 中的代码,加入一个用于启动 MyIntentService 这个服务的 按钮,如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical" >
……
<Button android:id="@+id/start_intent_service" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Start IntentService" />
</LinearLayout>
然后修改 MainActivity 中的代码,如下所示:

public class MainActivity extends Activity implements OnClickListener {
……
private Button startIntentService;

@Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
……
startIntentService = (Button) findViewById(R.id.start_intent_service);
startIntentService.setOnClickListener(this);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
……

case R.id.start_intent_service:
// 打印主线程的id
Log.d("MainActivity", "Thread id is " + Thread.currentThread().

getId());

Intent intentService = new Intent(this, MyIntentService.class);
startService(intentService);
break;

default:
break;
}
}
}
可以看到,我们在 Start IntentService 按钮的点击事件里面去启动 MyIntentService 这个服 务,并在这里打印了一下主线程的 id,稍后用于和 IntentService 进行比对。你会发现,其实 IntentService 的用法和普通的服务没什么两样。
最后仍然不要忘记,服务都是需要在 AndroidManifest.xml 里注册的,如下所示:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.servicetest"
android:versionCode="1"
android:versionName="1.0" >
……
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" >
……
<service android:name=".MyIntentService"></service>
</application>
</manifest>
现在重新运行一下程序,界面如图 9.13 所示。

图 9.13

点击 Start IntentService 按钮后,观察 LogCat 中的打印日志,如图 9.14 所示。

图 9.14

可以看到,不仅 MyIntentService 和 MainActivity 所在的线程 id 不一样,而且 onDestroy() 方法也得到了执行,说明 MyIntentService 在运行完毕后确实自动停止了。集开启线程和自动 停止于一身,IntentService 还是博得了不少程序员的喜爱。

android: 使用 IntentService的更多相关文章

  1. android基础---->IntentService的使用

    这一篇博客,我们开始前台服务与IntentServie源码分析的学习,关于service的生命周期及其简单使用,请参见我的博客:(android基础---->service的生命周期) 目录导航 ...

  2. Android开发--IntentService的用法,你错过了什么

    Android开发--IntentService的用法,你错过了什么 . 本文链接:https://blog.csdn.net/smbroe/article/details/45009721 Inte ...

  3. Android中IntentService与Service

    Android中的Service是用于后台服务的,当应用程序被挂到后台的时候,问了保证应用某些组件仍然可以工作而引入了Service这个概念,那么这里面要强调的是Service不是独立的进程,也不是独 ...

  4. android 中IntentService的使用场景

    IntentService是继承并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统的Service一样,同时,当任务执行 ...

  5. android 中IntentService的作用及使用

    IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service一样,同 ...

  6. 【Android】IntentService & HandlerThread源码解析

    一.前言 在学习Service的时候,我们一定会知道IntentService:官方文档不止一次强调,Service本身是运行在主线程中的(详见:[Android]Service),而主线程中是不适合 ...

  7. Android中IntentService的原理及使用

    在Android开发中,我们或许会碰到这么一种业务需求,一项任务分成几个子任务,子任务按顺序先后执行,子任务全部执行完后,这项任务才算成功.那么,利用几个子线程顺序执行是可以达到这个目的的,但是每个线 ...

  8. [Android Pro] Android中IntentService的原理及使用

    转载自:http://blog.csdn.net/ryantang03/article/details/8146154 在Android开发中,我 们或许会碰到这么一种业务需求,一项任务分成几个子任务 ...

  9. Android中IntentService详解

    简单说,IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service ...

随机推荐

  1. 解决 webx.ml 中The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path 问题

    在Eclipse 的项目  上,点击鼠标右键 选中 ,并 Finish 即可.

  2. hdu 5720 Wool

    hdu 5720 问题描述 黎明时,Venus为Psyche定下了第二个任务.她要渡过河,收集对岸绵羊身上的金羊毛. 那些绵羊狂野不驯,所以Psyche一直往地上丢树枝来把它们吓走.地上现在有n n ...

  3. css3新属性@ text-shadow

    text-shodow是css3的新属性,可以利用这个属性使字体更有立体感,还可以创造有趣的效果. 1.语法形式:text-shadow : x-offset(x轴偏移量) y-offset(y轴偏移 ...

  4. js抽奖

    http://www.aichengxu.com/view/64369 <!Doctype html><html><head><meta http-equiv ...

  5. 编写出色的GNU/Linux程序

    http://advancedlinuxprogramming.com提供了本书电子版的免费下载. 1 与执行环境交互 关于参数 C语言程序的main()函数使用两个参数和执行环境交互--(int)a ...

  6. STF(SmartPhone Test Farm)Mac版本环境搭建

    它的github页面为: https://github.com/openstf/stf 1.Linux一些基本包的安装: 在控制台分别运行 sudo apt-get update sudo apt-g ...

  7. NOIP2011 题解

    铺地毯 题解:比大小 #include <cstdio> +; int n, x, y, a[MAXN], b[MAXN], g[MAXN], k[MAXN]; inline int So ...

  8. 中兴手机关闭3G网络

    手机总是自动在2G和3G之间切换,关闭3G算了. 拨*983*683# 出来画面,然后选GSM Only即可 网上还有另一种方法: *#*#4636#*#* 在这个里,我没有找到GSM Only

  9. mybatis学习之路

    MyBatis 是支持普通SQL查询.存储过程和高级映射的优秀持久层框架. MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装. MyBatis可以使用简单的XML或注解 ...

  10. glRotate函数

    void glRotate( GLdouble angle, GLdouble x, GLdouble y, GLdouble z ) API说明:angle为旋转角度,单位为度:x,y,z是旋转轴的 ...