Service详解

772 阅读3分钟

1 Service应用场景,以及Service与Thread的区别

1.1 Service基础

  1. Service是什么?

    Service(服务)是一个可以在后台执行长时间操作而没有用户界面的应用组件。

    服务可有其他组件(Activity、broadcast)启动,服务一旦启动,就将在后台运行,即使启动的它的组件被销毁了,服务也不会受影响,也可以将service绑定到Activity,进行数据交互,不在同一进程时,通过进程间通信进行数据传输。Servive、broadcast都是运行在主线程,所以都不能做耗时操作。 Activity、Broadcast、Service ANR时间:

    Activity->5S

    Broadcast->10S

    Service->20S

  2. Service应用场景

    Service 是android的一种机制,当它运行的时候如果是Local Service,那么对应的 Service 是运行在主进程的 main 线程上的。如:onCreate,onStart 这些函数在被系统调用的时候都是在主进程的 main 线程上运行的。如果是Remote Service,那么对应的 Service 则是运行在独立进程的 main 线程上。因此请不要把 Service 理解成线程,它跟线程半毛钱的关系都没有!

    既然这样,那么我们为什么要用 Service 呢?其实这跟 android 的系统机制有关,我们先拿 Thread 来说。Thread 的运行是独立于 Activity 的,也就是说当一个 Activity 被 finish 之后,如果你没有主动停止 Thread 或者 Thread 里的 run 方法没有执行完毕的话,Thread 也会一直执行。因此这里会出现一个问题:当 Activity 被 finish 之后,你不再持有该 Thread 的引用。另一方面,你没有办法在不同的 Activity 中对同一 Thread 进行控制。

    举个例子:如果你的 Thread 需要不停地隔一段时间就要连接服务器做某种同步的话,该 Thread 需要在 Activity 没有start的时候也在运行。这个时候当你 start 一个 Activity 就没有办法在该 Activity 里面控制之前创建的 Thread。因此你便需要创建并启动一个 Service ,在 Service 里面创建、运行并控制该 Thread,这样便解决了该问题(因为任何 Activity 都可以控制同一 Service,而系统也只会创建一个对应 Service 的实例)。

    因此你可以把 Service 想象成一种消息服务,而你可以在任何有 Context 的地方调用 Context.startService、Context.stopService、Context.bindService,Context.unbindService,来控制它,你也可以在 Service 里注册 BroadcastReceiver,在其他地方通过发送 broadcast 来控制它,当然这些都是 Thread 做不到的。

  3. Service与Thread的区别

    Thread是程序执行的最小单元,是CPU分配资源的最小单位,工作线程中可以执行耗时操作,而主线程不可以;

    Service是Android中的一种特殊机制,是运行在主线程的,不能做耗时操作,Service与Activity不在同一进程时,需要使用IPC机制进行通信。

2 开启Service的两种方式

  1. startService

    1. 生命周期 oncreate()--->onstartcommand()--->onstart()--->onDestroy()
    2. 可以多次调用,不会重复创建,oncreate()只会执行一次以
    3. start方式开启的服务也只能停止一次,多次调用stopservice()是无效的
    4. 以start方式开启的服务与UI线程失去关系,即使UI线程被销毁,服务仍然可以正常运行
    5. 不能调用服务中的方法

    onStartCommend()返回值为START_STICKY时,表示如果Service因内存不足被系统杀掉后,一段时间,内存再次空闲的时候,会重新启动Service,再次调用onStartCommend(),但此时的Intent为空。

  2. bindService

    1. 生命周期 oncreate() --->onbind() -->onunbind()---->ondestry();
    2. 只能成功绑定和解绑一次。
    3. 与绑定的UI线程同时被销毁3.
    4. 可以调用服务中的方法

    使用方法:

    1. 创建BindService服务端,继承Service,并在类中创建一个实现Ibinder接口的实例对象,提供公共方法,给客户端调用。
    2. 在onBind()方法中,返回此Binder实例。
    3. 在客户端的onServiceConnected()回调中,接收Binder,并使用服务端提供的方法和Service进行通信。