Android 多线程:IntentService理解和使用总结
一、Android中的IntentService
1.1 主要作用
执行一些高优先级的后台任务。由于属于Service,若以比单纯的线程优先级更高。
1.2 原理
IntentService封装了HandlerThread和一个Handler。
- IntentService创建时启动一个HandlerThread,同时将Handler绑定HandlerThread。所以通过Handler发送的消息都在HandlerThread中执行。
- 然后IntentService进入生命周期
onStartCommand
再调用onStart
将传进的Intent对象以消息的形式使用Handler发送。 - Handler收到消息后会调用
onHandleIntent
这样一个抽象方法,这个方法需要我们自己实现去处理逻辑。最后处理完毕stopSelf(msg.arg1);
等待所有任务完成结束IntentService;
1.3 特点
继承了Service,是一个抽象类,必须创建子类才能使用。
二、IntentService使用
2.1 步骤以及例子
下面的例子使用IntentService执行两个异步任务,同时使用LocalBroadcastManager发送广播来通知两个任务的进度。
(1)IntentServiceTestActivity的布局两个按钮用于启动两个任务,两个ProgressBar分别显示任务。还有一个TextView用于显示Log。
(2)定义一个IntentService子类,必须创建构造函数传入参数作为IntentService的工作线程的名称。例子中有两个任务id用来处理和标记不同的进度信息。具体实现了循环增加count并及时发送给IntentServiceTestActivity更新UI。
public class IntentServiceTest extends IntentService {
...
// 必须创建该构造函数
public IntentServiceTest() {
super(IntentServiceTestActivity.TAG_MYINTENTSERVICE);
}
...
}
(3)IntentServiceTestActivity通过不同的按钮传递不同的intent用于启动IntentService。不同的参数标记任务id。
public void onClick(View v) {
switch (v.getId()){
case R.id.btn_task1:
Intent intentTask1 = new Intent(IntentServiceTestActivity.this,IntentServiceTest.class);
intentTask1.putExtra("taskId",0);
startService(intentTask1);
break;
case R.id.btn_task2:
Intent intentTask2 = new Intent(IntentServiceTestActivity.this,IntentServiceTest.class);
intentTask2.putExtra("taskId",1);
startService(intentTask2);
break;
}
}
(4)IntentServiceTest的onHandleIntent()
会持有传递来的intent对象,然后执行具体任务。
// 实际处理任务
@Override
protected void onHandleIntent(@Nullable Intent intent) {
sendThreadStatus("IntentServiceTest开始处理 --> onHandleIntent()");
// intent已经通过IntentService内部的Handler传递过来
int taskId = intent.getIntExtra("taskId",0);
if(taskId == 0){
startThread(0);
} else {
startThread(1);
}
}
//根据不同的taskId来标记不同的进度
private void startThread(int taskId){
try {
Thread.sleep(1000);
//发送线程状态
sendThreadStatus("线程启动 --> startThread()");
boolean runnIng = true;
mProgress[taskId] = 0;
while (runnIng){
mProgress[taskId] ++;
if(mProgress[taskId] >= 100){
runnIng = false;
}
sendThreadStatus("线程Running --> startThread()");
Thread.sleep(30);
}
sendThreadStatus("线程结束 --> startThread()");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
...
(5)上面的sendThreadStatus("")
方法通过广播发送线程状态:
/**
* 通过mLocalBroadcastManager发送IntentService的状态信息
* @param status
*/
private void sendIntentServiceStatus(String status) {
Intent intent = new Intent(IntentServiceTestActivity.ACTION_INTENTSERVICE_STATUS);
intent.putExtra("status",status);
mLocalBroadcastManager.sendBroadcast(intent);
}
/**
* 通过mLocalBroadcastManager发送工作线程的状态信息
* @param status
*/
private void sendThreadStatus(String status) {
Intent intent = new Intent(IntentServiceTestActivity.ACTION_THREAD_STATUS);
intent.putExtra("status",status);
intent.putExtra("progress",mProgress);
mLocalBroadcastManager.sendBroadcast(intent);
}
(6)IntentServiceTestActivity定义MyBroadcastReceiver接收上一步发送的广播消息更新ProgressBar进度。
public class MyBroadcastReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()){
case ACTION_INTENTSERVICE_STATUS:
mInfoText.setText(mInfoText.getText().toString()+"\n"+intent.getStringExtra("status"));
break;
case ACTION_THREAD_STATUS:
int[] progress = intent.getIntArrayExtra("progress");
mProgressBar1.setProgress(progress[0]);
mProgressBar2.setProgress(progress[1]);
mPb1.setText(progress[0]+"%");
mPb2.setText(progress[1]+"%");
mInfoText.setText(intent.getStringExtra("status"));
break;
}
}
}
(7)记得注册IntentService。<service android:name=".mythread.IntentServiceTest"/>
运行效果:
- 连续执行两次同一任务:
- 连续执行两个任务:
可以看到,无论是怎么添加任务,都是按顺序一个一个执行的。等所有任务执行完毕后IntentServiceTest执行了
onDestroy()
。
2.2 IntentService使用注意
- IntentService不建议使用
bindService()
方式使用,因为IntentService的onBind默认返回null。如果用Binder或Messenger 使其可以通信,则不会调用onHandleIntent()
方法,IntentService就只是一个普通的Service了。
public IBinder onBind(Intent intent) {
return null;
}
- IntentService一旦被停止,其中保存在消息队列中的任务都会被清除,也就不会执行。
相关文章:
Android多线程:理解和简单使用总结