欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

深入剖析Android系统中Service和IntentService的区别

程序员文章站 2024-03-01 17:36:52
android中的service是用于后台服务的,当应用程序被挂到后台的时候,问了保证应用某些组件仍然可以工作而引入了service这个概念,那么这里面要强调的是servi...

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的情况。