Android多线程编程之IntentService学习篇(三)
一、IntentService之初识
除非你特别指定,否则大部分在前台UI界面上的操作都执行在一个特殊的线程(UI线程)当中。这将会导致一些问题出现,因为耗时操作将会影响用户界面的响应性能。这比较困扰你的用户,而且还会导致一些系统问题出现。为了避免这些问题,Android Framework层提供了几个类用来帮助把那些耗时操作转移到后台来执行。在这些类中最常用的类就是IntentService。
IntentService是Service的子类,用来处理异步任务请求的类。客户端通过startService方法发送请求,这个Service是按需启动,通过工作线程来依次处理发送过来的意图,当任务执行完成后,IntentService会自动停止。
IntentService的优先级比线程更高,因为它是一种服务,因而IntentService比较适合执行一些高优先级的后台任务。
IntentService有以下几个局限性:
- 不可以直接和UI做交互。为了把它执行的结果展现在UI上,需要将结果发送给Activity。
- 工作队列是顺序执行的,如果一个任务正在IntentService中执行,此时再发送一个任务请求,这个任务会一直处于等待状态直到前面的任务执行完成。
- 正在执行的任务无法中断。
二、实例展示
这里将从三个步骤来说明如何使用IntentService:
- 创建IntentService
- 发送任务请求到IntentService
- 报告后台任务的执行状态
(1)创建IntentService
首先在项目中创建IntentService
public class IntentServiceTest extends IntentService {
public IntentServiceTest() {
super("IntentServiceTest");
}
@Override
protected void onHandleIntent(Intent intent) {
// Gets data from the incoming Intent
String dataString = intent.getStringExtra("intent data");
Log.v("IntentServiceTest", dataString);
...
// Do work here, based on the contents of dataString
...
}
}
再到AndroidManifest中定义IntentService,
<!--
因为android:export被设置为false,该服务职能在本应用中使用
-->
<service android:name=".IntentServiceTest"
android:exported="false"/>
(2)发送任务请求到IntentService
Intent intent = new Intent(this, IntentServiceTest.class);
intent.putExtra("intent data", "test");
startService(intent);
执行结果为:
```
(3) 报告后台任务的执行状态
创建BroadReceive
public class ResponseBroadCastReceiver extends BroadcastReceiver {
public static final String SERVICE_OUTPUT = “com.yishon.SERVICE_OUTPUT”;
public ResponseBroadCastReceiver() {}
@Override
public void onReceive(Context context, Intent intent) {
String dataString = intent.getStringExtra(“message”);
Log.v(“broadCastReceive”, dataString);
}
}
在Activity中的onCreate方法中执行以下代码
LocalBroadcastManager.getInstance(this).registerReceiver(new ResponseBroadCastReceiver(), new IntentFilter(ResponseBroadCastReceiver.SERVICE_OUTPUT));
在IntentServiceTest中的onHandleIntent方法执行
Intent msgIntent = new Intent(ResponseBroadCastReceive.SERVICE_OUTPUT);
msgIntent.putExtra(“message”, “This is my message!”);
LocalBroadcastManager.getInstance(this).sendBroadcast(msgIntent);
运行结果为:
```...V/broadCastReceive: This is my message!
<div class="se-preview-section-delimiter"></div>
三、工作原理分析
IntentService内部封装了Handler(mServiceHandler)和HandlerThread,在onCreate方法中实例化了这两个变量。
public void onCreate() {
// TODO: It would be nice to have an option to hold a partial wakelock
// during processing, and to have a static startService(Context, Intent)
// method that would launch the service & hand off a wakelock.
super.onCreate();
HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
}
<div class="se-preview-section-delimiter"></div>
在HandlerThread中的run方法创建Looper对象,因而mServiceLooper是从thread中获取Looper对象,并将其传给mServiceHandler.
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}
<div class="se-preview-section-delimiter"></div>
在handleMessage方法中会执行onHandleIntent方法,执行完后悔调用stopSelf(msg.arg1),当所有任务处理完后,IntentService会自动停止。
public int onStartCommand(Intent intent, int flags, int startId) {
onStart(intent, startId);
return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}
<div class="se-preview-section-delimiter"></div>
每次启动IntentService时都会调用onStartCommand方法,而进一步执行onStart方法。
public void onStart(Intent intent, int startId) {
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
msg.obj = intent;
mServiceHandler.sendMessage(msg);
}
而在onStart方法中主要是使用mServiceHandler发送消息,将任务消息发送给消息队列,进而Handler来处理消息,处理消息的时候是在HandlerThread线程当中执行的,其实也就是说onHandleIntent就是在HandlerThread线程中执行的。
每次启动一个IntentService,就发送一个任务来处理,所有的任务会按照一定启动的顺序来执行处理。