美文网首页Android
Android 多线程:IntentService理解和使用总结

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

作者: Marker_Sky | 来源:发表于2017-10-19 18:39 被阅读141次
    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多线程:理解和简单使用总结

    相关文章

      网友评论

        本文标题:Android 多线程:IntentService理解和使用总结

        本文链接:https://www.haomeiwen.com/subject/xpkpuxtx.html