Android

Android 多线程:IntentService理解和使用总结

2017-10-19  本文已影响141人  Marker_Sky
Android IntentService目录.png

一、Android中的IntentService

1.1 主要作用

执行一些高优先级的后台任务。由于属于Service,若以比单纯的线程优先级更高。

1.2 原理

IntentService封装了HandlerThread和一个Handler。

  1. IntentService创建时启动一个HandlerThread,同时将Handler绑定HandlerThread。所以通过Handler发送的消息都在HandlerThread中执行。
  2. 然后IntentService进入生命周期onStartCommand再调用onStart将传进的Intent对象以消息的形式使用Handler发送。
  3. 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"/>运行效果:

点击两次Task1.gif 两个Task点击.gif
可以看到,无论是怎么添加任务,都是按顺序一个一个执行的。等所有任务执行完毕后IntentServiceTest执行了onDestroy()

2.2 IntentService使用注意

  1. IntentService不建议使用bindService()方式使用,因为IntentService的onBind默认返回null。如果用Binder或Messenger 使其可以通信,则不会调用onHandleIntent()方法,IntentService就只是一个普通的Service了。
public IBinder onBind(Intent intent) {
        return null;
    }
  1. IntentService一旦被停止,其中保存在消息队列中的任务都会被清除,也就不会执行。

相关文章:
Android多线程:理解和简单使用总结

上一篇下一篇

猜你喜欢

热点阅读