Android之service探究

2023-06-08,,

首先,我们来看看service的英文翻译:    服务(名词) 、服务性的(形容词)。在android中service是如何解释的呢,下面是google的原文翻译:A Service is an application component that can perform long-running operations in the background and does not provide a user interface. Another application component can start a service and it will continue to run in the background even if the user switches to another application. Additionally, a component can bind to a service to interact with it and even perform interprocess communication (IPC).

       从上面的说明就可以知道service是什么了、是做什么的、可以做什么,其主要特点有一下几个方面:

(1):Service 是一个APP的component 。

(2):service 运行在后台的(in the background)、并且没有用户接口的。

(3):一个app的service 可以在该app退出时,仍然在后台正常运行。

(4):还有就是,一个service也可以和一个组件(activity)绑定,并可以进行进程间通信。

通过google的描述,我们基本上说明白Service。现在我们来看,Service到底是一个什么东西:

  首先,我们来看Service.java里面Service的定义:

public abstract class Service extends ContextWrapper implements ComponentCallbacks2 {
...

}
   看到这里,估计你会恍然大悟,原来也是一个Context子类。我们知道,Activity一样也是一个Context子类。
     所以,其实从某种意义上来讲Service和Activity本质是一样的。相对于Service来说,Activity只是还封装了一些与界面显示相关的方法和数据、以及实现了用户与app交流的一些像是按键事件处理、窗口信息等这样一类方法。因为,一个service根本没有可供前台显示、与用户交流的能力,所以可以理解我service是运行在后来的(Runing in the background)。
     所以,对于Service来说,一个Activity用于处理需要能够与用户直接交流的工作。相对于Activity来说,一个Service主要用于处理不需要与用户直接交流的工作,比如播放音乐(当我们推出音乐播放器的时候,音乐仍然还在播放,这里播放这个音乐就是用一个service来做的)。
    如何启动一个Service呢?Context中有启动、停止Service的方法,所以Activity和Service都是可以启动和停止一个Service。我们来看看Context中有启动、停止Service的方法(其具体的方法实现,在ContextImpl.java里):
public abstract ComponentName startService(Intent service);
        public abstract boolean stopService(Intent service);
public abstract boolean bindService(Intent service, ServiceConnection conn,int flags);
        public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) {
          throw new RuntimeException("Not implemented. Must override in a subclass.");
         }
public abstract void unbindService(ServiceConnection conn);
由此可见,启动一个Service其实有两种:Start和Bind。有什么区别呢?
     我们还是来看看google如何解释stopService的:
Using startService() overrides the default service lifetime that is managed by {@link #bindService}: it requires the service to remain running until {@link #stopService} is called, regardless of whether any clients are connected to it. 
       下面看看google如何解释bindService的:
This defines a dependency between your application and the service. 
The service will be considered required by the system only for as long as the calling context exists. 
        (1):从上面的解释可以知道,用startService()来启动一个Service, 该启动的service不依赖于这个启动他的app(Activity或者Service),几乎可以说和启动这个Service的Component没有其他关联,一般情况下,除非调用stopService()来停止这个Service,否则这个Service是不会因为其他原因被迫Stop的,当然这里说的也只是一般情况,往往还有一些特殊情况,如下google的解释:
The only time they should be stopped is if the current foreground application is using so many resources that the service needs to be killed. 
很显然这是一种特殊情况。只要我们知道,一般情况下系统会尽量让Startservice启动的Service保持运行状态的,除非stopService()方式来停止这个Service。
         (2):相比startService()来启动一个Service, BindService()启动一个Service就不一样了,从上面的google的意思可以知道:BindService()方式启动的Service和启动他的app是相互依赖的,其实更多的是这个Service依赖于这个APP。实际上android系统是这样觉得的:对于启动这个Service的Component(Activity/Service),如果这个Component(Activity/Service)都不存在了,那么这个被他启动的Service也是没有必要保留的。
         下面我们来看看Service的一个方法:public void onCreate()。这个方法在一个service实例化的时候才会调用,只要这个Service已经实例化了,这个函数当然就不可能再调用了。startService()和BindService()于其不一样,他们可以重复调用的。
         我们再来说一下Service这个函数public void onDestroy()。这个函数不是我们去调用的,主要是系统来要清除一个他认为无效的Service的时候调用的。
          接下来,要说最后一个问题:看到有人在网上问,既然Service是在后台运行的,那和定义一个Thread来来做这些工作有是不是是一样的呢? 回答当然是否定的,而且根本是风牛马不相及,下面一点点来解释:
         上面我们说了,其实一个Service和Activity一样,都是一个context的子类,本质上说其实是一样的。我们知道,一个APP运行在自己的进程中,该进程的有一个所谓的主线程(UI线程),其Activity的所有的动作都是在这个主线程运行的,比如布局、ImageView等组件绘制、按键事件、以及启动一个Activity等都是在这个主线程完成的。上面说了,Service和Activity本质一样的,所以其实一个Service所有的工作也都是在这个主线程完成的,他和Activity一样,也是可以自己启动一个独立的线程来处理其他事情的,以免阻塞了主线程!所以Service和Thread根本不是一回事!

《Android之service探究.doc》

下载本文的Word格式文档,以方便收藏与打印。