IntentService为在单一后台线程中执行任务提供了一种直接的实现方式。它可以处理一个耗时的任务并确保不影响到UI的响应性。另外IntentService的执行还不受UI生命周期的影响,以此来确保AsyncTask能够顺利运行。
但是IntentService有下面几个局限性:
- 不可以直接和UI做交互。为了把他执行的结果体现在UI上,需要把结果返回给Activity。
- 工作任务队列是顺序执行的,如果一个任务正在IntentService中执行,此时你再发送一个新的任务请求,这个新的任务会一直等待直到前面一个任务执行完毕才开始执行。
- 正在执行的任务无法打断。
虽然有上面那些限制,然而在在大多数情况下,IntentService都是执行简单后台任务操作的理想选择。
1.创建IntentService
创建一个IntentService组件,需要自定义一个新的类,它继承自IntentService,并重写onHandleIntent()方法
注意
一个普通Service组件的其他回调,例如onStartCommand()会被IntentService自动调用。在IntentService中,要避免重写那些回调。
public class MyService extends IntentService {
@Override
protected void onHandleIntent(Intent workIntent) {
dataString = workIntent.getDataString();
}}
2.在Manifest文件中定义IntentService
IntentService需要在manifest文件添加相应的条目。
注意
<service>标签并没有包含任何intent filter。因为发送任务给IntentService的Activity需要使用显式Intent,所以不需要filter。这也意味着只有在同一个app或者其他使用同一个UserID的组件才能够访问到这个Service。
<application
android:icon="@drawable/icon"
android:label="@string/app_name">
<service
android:name=".MyService"
android:exported="false"/>
<application/>
3.创建任务请求并发送到IntentService
一旦执行了startService(),IntentService在自己本身的onHandleIntent()方法里面开始执行这个任务,任务结束之后,会自动停止这个Service。
mServiceIntent = new Intent(getActivity(), MyService.class);
mServiceIntent.setData(Uri.parse(dataUrl));
getActivity().startService(mServiceIntent);
4.利用IntentService 发送任务状态
通过执行LocalBroadcastManager.sendBroadcast()来发送Intent。Intent被发送到任何有注册接受它的组件中。为了获取到LocalBroadcastManager的实例,可以执行getInstance()。
Intent localIntent = new Intent(Constants.BROADCAST_ACTION)
.putExtra(Constants.EXTENDED_DATA_STATUS, status);
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
5.接收来自IntentService的状态广播
为了接受广播的数据对象,需要使用BroadcastReceiver的子类并实现BroadcastReceiver.onReceive()的方法,这里可以接收LocalBroadcastManager发出的广播数据。
private class ResponseReceiver extends BroadcastReceiver{
DownloadStateReceiver() { }
public void onReceive(Context context, Intent intent) {
}}
一旦定义了BroadcastReceiver,也应该定义actions,categories与data用过滤广播。为了给系统注册这个BroadcastReceiver和IntentFilter,需要通过LocalBroadcastManager执行registerReceiver()的方法。
statusIntentFilter = new IntentFilter(Constants.ACTION_ZOOM_IMAGE);
LocalBroadcastManager.getInstance(getActivity())
.registerReceiver( mDownloadStateReceiver, mIntentFilter);
6.最后
使用LocalBroadcastManager结合IntentService其实是一种很典型高效的做法,同时也更符合OO的思想,通过广播注册与反注册的方式,对两个组件进行解耦。如果使用Handler传递到后台线程作为回调,容易带来的内存泄漏。原因是:匿名内部类对外面的Actvitiy持有引用,如果在Acitivity被销毁的时候,没有对Handler进行显式的解绑,会导致Activity无法正常销毁,这样自然就有了内存泄漏