IntentService 为在单一后台线程中执行任务提供了一种直接的实现方式。它可以处理一个耗时的任务并确保不影响到UI的响应性。另外 IntentService 的执行还不受 UI 生命周期的影响,以此来确保 AsyncTask 能够顺利运行。
但是 IntentService 有下面几个局限性:
不可以直接和 UI 做交互。为了把他执行的结果体现在UI上,需要把结果返回给 Activity。
工作任务队列是顺序执行的,如果一个任务正在IntentService中执行,此时你再发送一个新的任务请求,这个新的任务会一直等待直到前面一个任务执行完毕才开始执行。
正在执行的任务无法打断。
虽然有上面那些限制,然而在在大多数情况下,IntentService 都是执行简单后台任务操作的理想选择。
创建 IntentService
创建一个 IntentService 组件,需要自定义一个新的类,它继承自 IntentService,并重写onHandleIntent()
方法
注意
一个普通 Service 组件的其他回调,例如onStartCommand()
会被 IntentService 自动调用。在 IntentService 中,要避免重写那些回调。
public class MyService extends IntentService { @Override protected void onHandleIntent(Intent workIntent) { dataString = workIntent.getDataString(); }}
在 Manifest 文件中定义 IntentService
IntentService 需要在 manifest 文件添加相应的条目。
注意
标签并没有包含任何 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/>
创建任务请求并发送到 IntentService
一旦执行了startService()
,IntentService 在自己本身的onHandleIntent()
方法里面开始执行这个任务,任务结束之后,会自动停止这个 Service。
mServiceIntent = new Intent(getActivity(), MyService.class); mServiceIntent.setData(Uri.parse(dataUrl)); getActivity().startService(mServiceIntent);
利用 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);
接收来自 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);
最后
使用 LocalBroadcastManager 结合 IntentService 其实是一种很典型高效的做法,同时也更符合OO的思想,通过广播注册与反注册的方式,对两个组件进行解耦。如果使用 Handler 传递到后台线程作为回调,容易带来的内存泄漏。原因是:匿名内部类对外面的 Actvitiy 持有引用,如果在 Acitivity 被销毁的时候,没有对 Handler 进行显式的解绑,会导致 Activity 无法正常销毁,这样自然就有了内存泄露
共同学习,写下你的评论
评论加载中...
作者其他优质文章