android: 使用 IntentService
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的更多相关文章
- android基础---->IntentService的使用
这一篇博客,我们开始前台服务与IntentServie源码分析的学习,关于service的生命周期及其简单使用,请参见我的博客:(android基础---->service的生命周期) 目录导航 ...
- Android开发--IntentService的用法,你错过了什么
Android开发--IntentService的用法,你错过了什么 . 本文链接:https://blog.csdn.net/smbroe/article/details/45009721 Inte ...
- Android中IntentService与Service
Android中的Service是用于后台服务的,当应用程序被挂到后台的时候,问了保证应用某些组件仍然可以工作而引入了Service这个概念,那么这里面要强调的是Service不是独立的进程,也不是独 ...
- android 中IntentService的使用场景
IntentService是继承并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统的Service一样,同时,当任务执行 ...
- android 中IntentService的作用及使用
IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service一样,同 ...
- 【Android】IntentService & HandlerThread源码解析
一.前言 在学习Service的时候,我们一定会知道IntentService:官方文档不止一次强调,Service本身是运行在主线程中的(详见:[Android]Service),而主线程中是不适合 ...
- Android中IntentService的原理及使用
在Android开发中,我们或许会碰到这么一种业务需求,一项任务分成几个子任务,子任务按顺序先后执行,子任务全部执行完后,这项任务才算成功.那么,利用几个子线程顺序执行是可以达到这个目的的,但是每个线 ...
- [Android Pro] Android中IntentService的原理及使用
转载自:http://blog.csdn.net/ryantang03/article/details/8146154 在Android开发中,我 们或许会碰到这么一种业务需求,一项任务分成几个子任务 ...
- Android中IntentService详解
简单说,IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service ...
随机推荐
- Angular.js参考
http://www.cnblogs.com/popo123/p/5673955.html
- Java关键字:transient,strictfp和volatile简介
关键字:transient 使用对象:字段 介绍:transient说明一个属性是临时的,不会被序列化. 当对象进行序列化(Serializable)过程时候,有一些属性的状态是瞬时的,这样的对象是无 ...
- AngularJs自定义指令详解(3) - scope
我们之所以要定义指令,目的是重用指令.假设有这么一个应用场景:在同一个html里使用了两次my-directive,第一个my-directive要展示的是Hello World,第二个my-dire ...
- linux桌面环境gnome,kde,xfce,lxde 使用比较(转)
Linus Torvalds大神前几日在 Google+上表示,GNOME 3"无可容忍的凌乱",改投Xfce桌面环境.下面就GNOME, KDE, XFCE和 LXDE略作比较. ...
- 学习python之练习(三)
python排序算法 1.冒泡排序: import math def BubbleSort(list): lengthOfList = len(list) for i in range(0,lengt ...
- sql语句练习50题
Student(Sid,Sname,Sage,Ssex) 学生表 Course(Cid,Cname,Tid) 课程表 SC(Sid,Cid,score) 成绩表 Teacher(Tid,Tname) ...
- Android多点触控技术实战,自由地对图片进行缩放和移动
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/11100327 在上一篇文章中我带着大家一起实现了Android瀑布流照片墙的效果, ...
- 理解em,rem以及rem的失效问题
在平常做网站写代码的时候一般都是使用px,在之前的学习时就略微的学习了一些关于em.rem的知识,但是由于一直没有用到过,所以几乎全部忘记了.今天在研究一些知识的时候用到了em,所以特意将学到的知识总 ...
- 2.Unable to instantiate Action, templateAction, defined for 'template_list' in namespace '/'templateAction
1.错误说没有命名空间'templateAction,但是在struts里写了这个,名字跟Action的名字是一样的,为什么会报这个错误 2.反复检查路径和名字,都没有问题 3.发现没有对其进行注入操 ...
- NumberFormat usage
NumberFormat 是所有数值格式的抽象基类. 该类提供了格式化和分析数值的接口. NumberFormat 也提供了确定 哪个语言环境具有数值格式以及它们名字的方法. import java. ...