声明:翻译自谷歌官方培训教程,http://developer.android.com/intl/zh-cn/training/best-background.html。


启用Service




除非特殊指定,否则大部分操作都在一个被称为UI线程的特殊线程上运行。如果有耗时的操作也在UI线程上就会导致界面无响应的问题。为了解决这个问题,android框架提供了几个类来帮助你将耗时的操作放到其它的后台线程中进行。其中最有用的就是IntentService 。




本课程将介绍如何实现一个IntentService ,并向它发送请求 然后获得结果来与其他组件互动。




一、创建后台服务


IntentServiceIntentService 不受大多数用户界面的生命周期影响,所以即使在某些情况下需要关闭后台任务的时候它仍然在运行(但是执行完请求的操作后它会自己停止)。



一个 IntentService 有几点限制:

  • 它不可以直接与用户界面进行交互,要把结果通知给UI,必需把结果发送给Activity,让Activity来完成更新UI的操作。
  • 在它里面的请求是放在一个队列中的,如果有一个操作正在进行,那么再给IntentService发送请求的话,这个请求就会放到队列中进行等待直到第一个请求操作完成。
  • IntentService 中执行的操作不能被中断。



在大多数情况下IntentService 是首选的方式来简单的执行后台操作。




本小节将展示如何创建IntentService  的子类,如何建立必要的回调方法onHandleIntent() ,最后介绍如何在 manifest文件中声明 IntentService 。




1.创建一个 IntentService


要创建一个IntentService组件,需要声明一个类继承自IntentService然后重写 onHandleIntent()

public class RSSPullService extends IntentService {
    @Override
    protected void onHandleIntent(Intent workIntent) {
        // Gets data from the incoming Intent
        String dataString = workIntent.getDataString();
        ...
        // Do work here, based on the contents of dataString
        ...
    }
}

需要注意的是对于正规的服务的其它的回调方法不应该在这里重写,例如

onStartCommand() 方法, 这些回调在IntentService中已经实现好了。




2.在manifest文件中声明IntentService


IntentService是Service的子类,所以声明就和Service声明一样的。


<application
        android:icon="@drawable/icon"
        android:label="@string/app_name">
        ...
        <!--
            Because android:exported is set to "false",
            the service is only available to this app.
        -->
        <service
            android:name=".RSSPullService"
            android:exported="false"/>
        ...
    <application/>

其中android

:name 属性的值是继承自IntentService类的名称。


需要注意的是,在这里<service> 元素下没有intent filter。Activity通过明确的Intent向IntentService发送请求,所以没有 intent filter是必要的。





二、向后台服务发送操作请求


本小节讲述,如何向IntentService发送一个Intent来请求后台操作,Intent中包含需要IntentService处理的数据。可以从Activity或者Fragment中任何节点向IntentService发送请求。




1.创建和发送工作请求到IntentService


由于IntentService没有指定intent filter 所以只能发送显式的Intent


/*
 * Creates a new Intent to start the RSSPullService
 * IntentService. Passes a URI in the
 * Intent's "data" field.
 */
mServiceIntent = new Intent(getActivity(), RSSPullService.class);
mServiceIntent.setData(Uri.parse(dataUrl));

请求服务,调用

startService()

      方法。

// Starts the IntentService
getActivity().startService(mServiceIntent);




一旦调用 startService()方法,IntentService就在声明的 onHandleIntent()方法中来执行请求的操作,执行完了就自己停止。




三、汇报IntentService异步操作的状态


使用LocalBroadcastManager 发送广播实现。