Service不彻底解析

本篇的内容并非介绍service使用方法和生命周期的,而是对其中的一些要点进行记录和分析。html

        咱们都知道,Service是一个在后台执行的应用组件,用于在后台进行长期操做,例如进行网络事务,播放背景音乐等等。它又两种启动方式,若是其余的应用组件但愿与该service进程内通讯(IPC),能够经过与该service绑定来实现。关于生命周期的问题就不啰嗦了,直接放官档的图:android

image

        不管何种方式启动service,任何应用组件均可以使用该service。若是但愿只有你本身的app才能使用该service,那么须要在manifest文件中加入android:exported属性,并将其设置为false。Android官方建议咱们尽可能使用显式的方式来启动service,从而保证app的安全。安全

        另外,咱们须要注意的是,在默认状况下service并不会从新开启一个独立的线程运行,而是运行于宿主进程的主线程中。显然,若是咱们须要进行耗时操做,例如上面提到的播放背景音乐,网络操做等等,该如何解决?网络

    • 咱们能够在activity中建立新线程,并在activity中对线程进行建立启动和销毁;
    • 使用asyncTask来完成任务;
    • 在service中新开一个线程来完成这些任务,以防ANR错误。

IntentService       多线程

        当咱们不须要同时处理多个请求的状况下,咱们最好的解决方案是使用IntentService完成任务,而咱们只需重写onHandleIntent()来完成处理逻辑便可。在IntentService进行了如下工做:并发

    • 新启动了一个worker线程来执行那些提交给onStartComand方法的intent任务。
    • 建立了一个work队列来存放多个请求任务,每次只向onHandleIntent()方法来传递一个intent来处理。
    • 当全部请求任务都完成后,则自动中止该service。
    • 默认的onStartCommand()方法中,将收到的intent参数传递给onHandleIntent()来处理。

        下面是一个IntentService的示例:app

public class HelloIntentService extends IntentService {

  /**
   * A constructor is required, and must call the super IntentService(String)
   * constructor with a name for the worker thread.
   */
  public HelloIntentService() {
      super("HelloIntentService");
  }

  /**
   * The IntentService calls this method from the default worker thread with
   * the intent that started the service. When this method returns, IntentService
   * stops the service, as appropriate.
   */
  @Override
  protected void onHandleIntent(Intent intent) {
      // Normally we would do some work here, like download a file.
      // For our sample, we just sleep for 5 seconds.
      long endTime = System.currentTimeMillis() + 5*1000;
      while (System.currentTimeMillis() < endTime) {
          synchronized (this) {
              try {
                  wait(endTime - System.currentTimeMillis());
              } catch (Exception e) {
              }
          }
      }
  }
}

        这里只需实现一个简单的构造函数和intent处理方法就能够了。固然,咱们也能够根据须要重写service生命周期中的其余方法,可是请记得调用父类方法。咱们须要清楚的是,全部提交给该service的任务都以intent的形式存放于一个队列中,IntentService里惟一的worker线程每次取一个intent来处理,都处理完后自动关闭IntentService。async

        若是但愿多线程并发处理任务,那么须要继承service来处理任务了。这里就不演示具体代码了,可是有一点须要提醒一下。在onStartCommand方法会返回一个int值,一般咱们返回父类的方法,这里的int值描述了当系统干掉service后的操做,它的几个常量选项以下:ide

    • START_NOT_STICKY当onStartCommand方法返回后,系统杀死了service,除非又有intent请求传递进来,不然将不会从新启动service。该选项能够很安全地确保当应用程序重启那些未完成的工做,而并不须要运行service时,避免service的启动运行。
    • START_STICKY当onStartCommand方法返回后,系统杀死了service,那么将会从新启动service,并执行onStartCommand方法,可是从新传递进来的intent并非上一个intent了,而是使用null来代替(除非有新的intent请求)。该选项适用于相似于媒体播放器这种service,不执行任何命令,只是一直在运行等待任务。
    • START_REDELIVER_INTENT当onStartCommand方法返回后,系统杀死了service,那么将会从新启动service,并执行onStartCommand方法,从新传递进来的intent与上一个相同,随后而来的intent请求将会依次执行。该选项适用于相似下载任务的service,一直处于活跃状态,一旦挂掉就须要当即恢复。

        另外,service还经常与notification相结合使用,使service能够运行到前台,例如音乐播听任务等等,能够与用户交互,这些内容之后再介绍。函数

相关文章
相关标签/搜索