博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android Service:Creating a Started Service
阅读量:6911 次
发布时间:2019-06-27

本文共 7284 字,大约阅读时间需要 24 分钟。

 

Creating a Started Service

 

  一个被开始的service(started service)是另一个组件调用开启的,结果是这个service的方法被调用。

  当一个service被start,它就拥有一个独立于开始它的组件的生命周期,这个service可以无限地在后台运行,即使开始它的那个组件被销毁了。

  所以,service应该在完成工作后自己停止,通过调用,或另一个组件可以通过调用来停止它。

 

  简单说,就是: 

  一个应用组件,比如activity可以开启一个 service,通过调用 方法并传递一个定制service和传递必要数据的intent对象。

  Service会在 方法中获取这个对象。

 

  举个例子,一个activity需要把一些数据存储在一个网络上的数据库里,这个activity可以开启一个service,把要存储的数据通过一个中的intent参数传递给service,service在 方法中得到这个intent,建立网络连接并执行数据库事务。当事务处理完毕,service自己停止自己并销毁。

  注意:默认情况下,service运行在声明它的应用的同一个进程里面,而且在应用的主线程里面。

  所以,如果你的service需要执行一些繁重的或者阻塞性的工作,同时用户要和同一个应用中的activity进行交互,service会降低activity的性能。

  为了避免妨碍应用性能,你应该在service中新开启一个线程。

 

可以继承两个类去创建一个started service

  这是所有service的基类。

  当你继承这个类时,比较重要的一点就是你需要创建一个新的线程,在里面做所有service的工作,因为这个service默认情况下会使用应用的主线程,这样会降低你的应用中正在运行的activity的性能。

 

  这是一个Service类的子类,它使用一个工作线程(worker thread)来处理所有的开启请求,一次一个。

  如果你不要求你的service同时处理多个请求的话,这是你最好的选择。

  你需要做的仅仅是实现 方法,它将接收到每一个start请求的intent,所以你可以做后台的工作。

 

Extending the IntentService class

  因为多数的service不需要同时处理多个请求,所以你可以使用 来实现你自己的service。

   做了如下的工作:

  1.创建一个默认的worker thread,与应用的主线程分离,处理所有传递给 方法的intent。

  2.建立一个工作队列,一次传递一个intent给 ,所以你永远不用担心多线程问题。

  3.当所有的start请求都被处理以后,停止service,所以你永远不必去调用 

  4.提供了 的默认实现,返回null。

  5.提供了 的默认实现,把intent传向工作队列,然后传向  的实现。

  所有的这些加起来,说明事实上你需要做的事情就仅仅是实现方法去做客户端提供的工作。

  当然,你还需要提供一个构造方法,它必须调用基类的IntentService(String)构造方法

 

  下面是一个实现例子:

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)          {              }          }      }  }}

 

  如果你决定覆写一些其他的回调方法,比如 , or 请确定一定要调用基类的实现这样IntentService才能正确地管理worker线程的生命

  比如, 必须返回默认的实现(这是有关intent被传递到 的)。

 

@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {    Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();    return super.onStartCommand(intent,flags,startId);}

 

  除了 还有仅一个方法中你不需要调用基类,那就是 ,不过你仅仅在你的service允许绑定的时候需要实现它。

 

Extending the Service class

  如果你需要你的service去执行多线程,而不是通过一个工作队列处理开始请求,你可以继承 来处理每一个intent。

  为了比较,下面是一个继承了Service类的实现,做的工作和上面继承IntentService的完全相同:

直接继承Service类的实现
public class HelloService extends Service{    private Looper mServiceLooper;    private ServiceHandler mServiceHandler;    // Handler that receives messages from the thread    private final class ServiceHandler extends Handler    {        public ServiceHandler(Looper looper)        {            super(looper);        }        @Override        public void handleMessage(Message msg)        {            // 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)                    {                    }                }            }            // Stop the service using the startId, so that we don't stop            // the service in the middle of handling another job            stopSelf(msg.arg1);        }    }    @Override    public void onCreate()    {        // Start up the thread running the service. Note that we create a        // separate thread because the service normally runs in the process's        // main thread, which we don't want to block. We also make it        // background priority so CPU-intensive work will not disrupt our UI.        HandlerThread thread = new HandlerThread("ServiceStartArguments",                Process.THREAD_PRIORITY_BACKGROUND);        thread.start();        // Get the HandlerThread's Looper and use it for our Handler        mServiceLooper = thread.getLooper();        mServiceHandler = new ServiceHandler(mServiceLooper);    }    @Override    public int onStartCommand(Intent intent, int flags, int startId)    {        Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();        // For each start request, send a message to start a job and deliver the        // start ID so we know which request we're stopping when we finish the        // job        Message msg = mServiceHandler.obtainMessage();        msg.arg1 = startId;        mServiceHandler.sendMessage(msg);        // If we get killed, after returning from here, restart        return START_STICKY;    }    @Override    public IBinder onBind(Intent intent)    {        // We don't provide binding, so return null        return null;    }    @Override    public void onDestroy()    {        Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();    }}

 

  可以看到,与使用IntentService相比,我们需要做更多的工作,但是,因为你自己处理的每一次调用,所以你可以同时执行多个请求。

  这个例子没有这样做,如果你想要同时处理多个请求,你可以为每个请求创建一个新的线程,然后立即执行它们,而不是等待上一个请求执行完毕再执行。

 

  注意到方法必须返回一个整形,这个整形描述了系统应该如何继续被系统kill掉的service,

  返回值必须是下列常量之一:

  如果在  方法返回后系统将service销毁,不重建service,除非有pending intent被传递。

  这是最安全的一种选择,可以避免运行service在不必要的时候,和当你的应用可以重新开始未完成的工作的时候。

  如果在  方法返回后系统将service销毁,重建service,并且调用方法,但是不重新传递上一个intent

  系统调用 方法时传递一个null intent。

  除非有pending intent来开启这个service,在这种情况下,pending intent是被传递的。

  这种情况对于多媒体播放器(或者其他类似的service)比较适合,它们不执行命令,但是它们等待工作并无限执行。

  如果在  方法返回后系统将service销毁,重建service,并且调用方法,上一个intent将会被传递给service

  任何的pending intent将顺次被传递。

  这对于积极执行一项工作的service非常适合,因为它们应该被立即恢复,比如下载文件。

 

Starting a Service

  你可以从一个activity或其他组件通过方法来开始一个service,需要传递一个Intent对象来指定要开启的service。

  Android系统会调用service的方法然后把Intent对象传递给它。

  比如:

Intent intent = new Intent(this, HelloService.class);startService(intent);

 

   方法会立即返回,Android系统会调用service的方法,如果service不是已经在运行,那么系统会先调用它的 方法,然后调用

  如果service没有同时提供绑定,那么传递给 方法的intent对象是调用组件和service之间唯一的交流形式。

  但是,如果你想要service发送一个结果回来,那么开启service的客户可以为broadcast创建一个,(用方法),然后把它作为开启service的intent传给service。这个service之后就可以使用这个broadcast来传递一个结果。

  多次的开启请求会导致多次的方法被调用,然而,只需要一个停止的请求 (with  or ) 就可以将service停止。

 

Stopping a service

  一个被开始的service必须管理自己的生命周期。

  即,系统不会停止或者销毁service(除非系统必须恢复一些内存),service将会在  方法返回之后一直持续运行。

  所以,service必须通过来停止自己,或者另一个组件通过来停止它。

  一旦通过  or 方法发送了停止的请求,系统将会尽快销毁service。

 

  然而,如果你的service并行处理多个请求,那么在你不应该在你处理完一个start请求之后stop这个service。因为你可能得到了一个新的start请求。(在第一个请求之后停止,有可能会终止第二个。)

  为了避免这个问题,你可以使用 来确保你要停止的请求永远基于最近开始的service。

  即是说,当你调用 时,你将start请求的ID  (the startId delivered to)传递过去。

  这样如果你的service在你的调用前得到一个新的start请求,由于ID不匹配,这个service不会被stop。

 

  注意:当service做完它的工作时,你的应用应该停掉它。这样可以避免系统资源浪费和电池能量消耗。

  如果有必要,其他组件可以通过来停止service。

  即便你允许绑定service,如果你的service有得到方法的调用,你就永远必须自己停止它。

 

参考资料

  API Guides:Services

  

转载地址:http://vtncl.baihongyu.com/

你可能感兴趣的文章
1.数码相框-相框框架分析(1)
查看>>
Javascript中的原型继承具体解释
查看>>
Python基础之(三)----PyGame安装步骤
查看>>
MYSQL SHOW VARIABLES简介
查看>>
Win8Metro(C#)数字图像处理--2.8图像线性变换
查看>>
解决eclipse不识别Android手机的问题
查看>>
axel命令 文件下载
查看>>
python基础训练题1-列表操作
查看>>
编程学习资源
查看>>
selenium+python自动化95-弹出框死活定位不到
查看>>
[Asp.net core]使用Polly网络请求异常重试
查看>>
Java探针-Java Agent技术-阿里面试题
查看>>
densenet
查看>>
user-agent
查看>>
基于Redis+MySQL+MongoDB存储架构应用
查看>>
thymeleaf 的hello world
查看>>
js pjax 和window.history.pushState,replaceState
查看>>
Hadoop Yarn REST API未授权漏洞利用挖矿分析
查看>>
asp.net Core 获取应用程序所在目录的2种方式
查看>>
Android震动vibrator(马达)--系统到驱动的流程【转】
查看>>