深入剖析Android系统中Service和IntentService的区别
作者:matrix_xu 发布时间:2023-06-29 17:55:16
Android中的Service是用于后台服务的,当应用程序被挂到后台的时候,问了保证应用某些组件仍然可以工作而引入了Service这个概念,那么这里面要强调的是Service不是独立的进程,也不是独立的线程,它是依赖于应用程序的主线程的,也就是说,在更多时候不建议在Service中编写耗时的逻辑和操作,否则会引起ANR。
那么我们当我们编写的耗时逻辑,不得不被service来管理的时候,就需要引入IntentService,IntentService是继承Service的,那么它包含了Service的全部特性,当然也包含service的生命周期,那么与service不同的是,IntentService在执行onCreate操作的时候,内部开了一个线程,去你执行你的耗时操作。
service本身存在两个问题:
(1)service不会专门启动一条单独的进程,service与它所在的应用位于同一个进程。
(2)service也不是专门新的一条线程,不应该在service中处理耗时的操作。
IntentService很好的弥补了这一点:
(1)IntentService会创建单独的worker线程来处理所有的intent请求。
(2)IntentService会创建单独的worker线程来处理onHandleIntent()方法实现的代码。
(3)当所有的请求处理完之后,IntentService会自动停止。
(4)为Service的OnBind()方法提供了默认的实现,返回null。
(5)为service的onStartCommand()方法提供了默认的实现,该实现会将请求intent添加到队列中。
所以对IntentService的使用就是:继承IntentService,重写onHandleIntent()方法即可。
tips:
(1)Intentservice也必须在manifest中声明。
(2)实现类的构造方法必须实现默认的构造方法。
这里我 需要解释以下几个方法,也许大家都已经很清楚了,不过为了抛砖引玉,我还是要提一嘴。
Service中提供了一个方法:
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}
这个方法的具体含义是,当你的需要这个service启动的时候,或者调用这个servcie的时候,那么这个方法首先是要被回调的。
同时IntentService中提供了这么一个方法:
protected abstract void onHandleIntent(Intent intent);
这是一个抽象方法,也就是说具体的实现需要被延伸到子类。
子类的声明:
public class ChargeService extends IntentService
上面提到过IntentService是继承Service的,那么这个子类也肯定继承service,那么onHandleIntent()方法是什么时候被调用的呢?让我们具体看IntentService的内部实现:
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
/**
* Creates an IntentService. Invoked by your subclass's constructor.
*
* @param name Used to name the worker thread, important only for debugging.
*/
public IntentService(String name) {
super();
mName = name;
}
/**
* Sets intent redelivery preferences. Usually called from the constructor
* with your preferred semantics.
*
* <p>If enabled is true,
* {@link #onStartCommand(Intent, int, int)} will return
* {@link Service#START_REDELIVER_INTENT}, so if this process dies before
* {@link #onHandleIntent(Intent)} returns, the process will be restarted
* and the intent redelivered. If multiple Intents have been sent, only
* the most recent one is guaranteed to be redelivered.
*
* <p>If enabled is false (the default),
* {@link #onStartCommand(Intent, int, int)} will return
* {@link Service#START_NOT_STICKY}, and if the process dies, the Intent
* dies along with it.
*/
public void setIntentRedelivery(boolean enabled) {
mRedelivery = enabled;
}
@Override
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
@Override
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
在这里我们可以清楚的看到其实IntentService在执行onCreate的方法的时候,其实开了一个线程HandlerThread,并获得了当前线程队列管理的looper,并且在onStart的时候,把消息置入了消息队列,
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
在消息被handler接受并且回调的时候,执行了onHandlerIntent方法,该方法的实现是子类去做的。
结论:
IntentService是通过Handler looper message的方式实现了一个多线程的操作,同时耗时操作也可以被这个线程管理和执行,同时不会产生ANR的情况。
猜你喜欢
- C++的函数指针(function pointer)是通过指向函数的指针间接调用函数。相信很多人对指向一般函数的函数指针使用的比较多,而对指
- 本文实例讲述了C#使用iTextSharp封装的PDF文件操作类。分享给大家供大家参考。具体分析如下:这个C#代码主要讲iTextSharp
- 准备工具:IDEAjdk1.8Navicat for MySQLPostman一、新建Project选择依赖:mybatis Web Mys
- 前言大家都知道网络操作的响应时间是不定的,所有的网络操作都应该放在一个异步操作中处理,而且为了模块解耦,我们希望网络操作由专门的类来处理。所
- /* * 名称:RandomId * 功能:生成随机ID * 作者:冰麟轻武 * 日期:2012年1
- 本文实例讲述了Android中显示GIF动画的实现代码。分享给大家供大家参考,具体如下:gif图动画在android中还是比较常用的,比如像
- SSM@Controller,@Service本质都是@Component,作用是new对象放到Spring容器里。controller层@
- 这篇文章主要介绍了Java CPU性能分析工具代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋
- 目录1. 简单认识BeanProcessorBeanProcessor的理解一个BeanProcessor的使用实例2. BeanProce
- 本文实例为大家分享了android自定义环形统计图动画的具体代码,供大家参考,具体内容如下一、测试截图二、实现原理 package
- 默认配置默认配置比较低,打开稍大点的项目就很容易卡掉,所以最好扩大一下内存。IntelliJ IDEA的VM配置IntelliJ IDEA2
- 一 问题描述小明为位置1,求他到其他各顶点的距离。二 实现package graph.dijkstra;import j
- 什么是ListView分页加载数据功能呢?在现在的大数据时代,我们不可能把某些数据全部展示到界面,好比我们经常会看的QQ空间一样,当你看动态
- 在开发中经常使用到Set集合去重,那么去重的原理是怎样实现的呢?在此文章记录一下去重原理!!!下面是set集合类图下面我们来跟踪一下执行过程
- C语言时用if...else...来控制异常,Java语言所有的异常都可以用一个类来表示,不同类型的异常对应不同的子类异常,每个异常都对应一
- 当我们第一次下载QQ并且打开的时候,会有一个新手引导,引导是几张图片,再加上一些文字说明,向右滑动,直到结束,今天一大早起来研究了一下关于此
- 我们通常在使用Java 调用脚本的时候,会使用 Runtime 类如:// 打开浏览器并访问 http://localh
- .NET包含一个特殊的Object类,可以接受任意的数据类型的值,当所传递或所赋值的类型不是一个特定的数据类型时,object类就提供了一种
- Android横竖屏切换时,当前的Activity会被销毁,然后Activity上面的数据将会全部丢失。如Listview上面每个item的
- 博主说:有时候,我们需要对数据库中现有的数据进行大量处理操作(例如表中的某个字段需要全部更新等),如果直接使用select * from t