Handler 原理分析和使用之HandlerThread

前面已经提到过Handler的原理以及Handler的三种用法。这里做一个非常简单的一个总结:

  • Handler 是跨线程的Message处理。负责把Message推送到MessageQueue和处理。
  • Looper 用来轮询MessageQueue,获取Message 发送给指定的Handler进行处理。
  • Looper 需要和线程绑定,绑定那个线程,Handler就会在那个线程处理Message

前两篇文章使用Handler处理的场景是:主线程(UI线程)被子线程更新。即使用主线程的Handler和Looper,在子线程中发Message。然后主线程处理 handlerMessage。

-----------------------------------------------------------------------------------------

下面反过来说,如何从UI线程发消息,让子线程处理。

最为通常的做法是:new Thread().start。起一个线程去完成一个任务,任务完成线程就可以自毙了。当然了如果不需要子线程返回结果,而且只有一个线程,那么这是最简单的了。

另一种方法是SyncTask。实例如下:

 1 import android.os.AsyncTask;
 2 import android.support.v7.app.AppCompatActivity;
 3 import android.os.Bundle;
 4 import android.view.View;
 5 import android.widget.Button;
 6 import android.widget.TextView;
 7 
 8 
 9 public class MainActivity extends AppCompatActivity implements View.OnClickListener{
10 
11     private TextView myTextView;
12     private Button myButton;
13     private MyAsyncTask myTask;
14     @Override
15     protected void onCreate(Bundle savedInstanceState) {
16         super.onCreate(savedInstanceState);
17         setContentView(R.layout.activity_main);
18         myTextView = (TextView)this.findViewById(R.id.text_view);
19         myButton = (Button)this.findViewById(R.id.post);
20         myButton.setOnClickListener(this);
21         //主线程初始化异步任务
22         myTask = new MyAsyncTask();
23         //主线程启动异步任务,
24         myTask.execute(10);
25     }
26 
27     @Override
28     public void onClick(View v) {
29         //主线程取消异步任务
30         myTask.cancel(true);
31     }
32 
33     /**
34      * AsyncTask<T, Q, K> 是异步任务基类  包含三个泛型参数。
35      * T 类型参数为执行异步任务时的参数类型doInBackground(T)
36      * Q 类型参数为执行过程中的参数类型onProgressUpdate(Q)
37      * K 类型参数为执行结束onPostExecute(K)或中取消执行时的类型参数onCancelled(K)
38      */
39     class MyAsyncTask  extends AsyncTask<Integer, Integer, Long>{
40 
41         @Override
42         //执行异步任务核心方法,主语T参数类型
43         protected Long doInBackground(Integer... params) {
44             int size = params[0];
45             long totalSize = 0l;
46             for(int i = 0; i < size; i++){
47                 totalSize += 10000;
48                 publishProgress((int) ((i / (float) size) * 100));
49                 if(isCancelled()){
50                     break;
51                 }
52                 try {
53                     Thread.sleep(1000);
54                 } catch (InterruptedException e) {
55                     e.printStackTrace();
56                 }
57             }
58             return totalSize;
59         }
60 
61         @Override
62         //开始执行异步任务前,更新UI线程。
63         protected void onPreExecute() {
64             myTextView.setText("downLoad start !!");
65         }
66 
67         @Override
68         //执行异步任务中,更新UI线程
69         protected void onProgressUpdate(Integer... values) {
70             int progress = values[0];
71             myTextView.setText(progress + "%");
72         }
73 
74         @Override
75         //执行异步任务后,更新UI线程
76         protected void onPostExecute(Long aLong) {
77             myTextView.setText("Task finished");
78         }
79 
80         @Override
81         //执行异步任务被取消后,跟新UI线程
82         protected void onCancelled(Long aLong) {
83             myTextView.setText("Task camcelled");
84         }
85     }
86 }

 

通过实例可以看出,SyncTask不但可以给主线程提供启动和停止接口,还可以给主线程上报过程。当然了开销也是有的。

实际上这种方式也可以用 Handler 原理分析和使用(一)中的例子实现。

 

以上都是主线程启动一个子线程完成任务。但是如果要做多个异步任务,该如何实现?

首先,从多个异步任务来考虑,如果还是各自不同的话,先考虑到的是线程池。这个在后面的多线程部分在说明。

还有一种方式就是使用HandlerThread。这个就是通过主线程获取其他线程给HandlerThread发消息,使其完成相关的任务。在例举说明HandlerThread使用之前,先看看以下例子。也是主线程给子线程发消息,让子线程处理任务。

 1 import android.os.Handler;
 2 import android.os.Looper;
 3 import android.os.Message;
 4 import android.support.v7.app.AppCompatActivity;
 5 import android.os.Bundle;
 6 import android.util.Log;
 7 import android.view.View;
 8 import android.widget.Button;
 9 import android.widget.TextView;
10 import java.util.concurrent.ArrayBlockingQueue;
11 import java.util.concurrent.BlockingQueue;
12 
13 
14 public class MainActivity extends AppCompatActivity implements View.OnClickListener{
15 
16     private TextView myTextView;
17     private Button myButton;
18     private MyThread myThread;
19     private Handler myThreadHandler;
20     private int count = 0;
21     @Override
22     protected void onCreate(Bundle savedInstanceState) {
23         super.onCreate(savedInstanceState);
24         setContentView(R.layout.activity_main);
25         myTextView = (TextView)this.findViewById(R.id.text_view);
26         myButton = (Button)this.findViewById(R.id.post);
27         myButton.setOnClickListener(this);
28         //定义子线程
29         myThread = new MyThread();
30         //获取子线程的Handler
31         myThreadHandler = myThread.getHandler();
32         //启动子线程
33         myThread.start();
34 
35     }
36 
37     @Override
38     public void onClick(View v) {
39         count++;
40         //通过子线程的Handler,主线程给子线程发送消息(添加任务)
41         myThreadHandler.sendEmptyMessage(count);
42     }
43 
44     /**
45      * 子线程
46      */
47     public class MyThread extends Thread{
48         public Handler mThreadHandler = null;
49         //任务队列
50         public BlockingQueue<Integer> queue  = null;
51         public MyThread(){
52             super();
53             queue  = new ArrayBlockingQueue<Integer>(20);
54             //获取子线程的Looper
55             Looper mThreadLopper = Looper.myLooper();
56             //初始化子线程的Handler
57             mThreadHandler = new Handler(mThreadLopper, new Handler.Callback() {
58                 @Override
59                 //接收到主线程发的任务
60                 public boolean handleMessage(Message msg) {
61                     //任务添加到队列
62                     queue.add(msg.what);
63                     return false;
64                 }
65             });
66         }
67         public Handler getHandler(){
68             return mThreadHandler;
69         }
70         public void run(){
71             while(true){
72                 try{
73                     //任务的处理
74                     int what = queue.take();
75                     Log.e("Test", "Click Button = " + what);
76                 }catch(InterruptedException e){
77 
78                 }
79 
80             }
81         }
82 
83     }
84 }

上面的例子说明了两件事情。第一,非主线程有自己的Looper(很多文章说没有),第二Handler可以处理非主线程的任务。实际上上面的例子,使用了sendMessage()方法,其实际上用处并不是很广泛,甚至有些憋屈,本身已经有了一个MessageQueue,为什么还要使用一个ArrayBlockingQueue?

实际上上述的例子,完全可以通过HandlerThread来替代。例子如下

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

    public TextView myTextView;
    private Button myButton;
    private HandlerThread myThread;
    private Handler myThreadHandler;
    private int count = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myTextView = (TextView)this.findViewById(R.id.text_view);
        myButton = (Button)this.findViewById(R.id.post);
        myButton.setOnClickListener(this);
        //初始化HandlerThread
        myThread = new HandlerThread("handlerThread_test");
        //启动HandlerThread
        myThread.start();
        //初始化HandlerThrand的Handler对象
        myThreadHandler = new Handler(myThread.getLooper(), new Handler.Callback() {
            @Override
            //实现消息处理。
            public boolean handleMessage(Message msg) {
                int what =msg.what;
                Log.e("Test", "Click Button = " + what);
                return false;
            }
        });
    }

    @Override
    public void onClick(View v) {
        count++;
        //通过Handler给HandlerThread线程发送消息
        myThreadHandler.sendEmptyMessage(count);
        //通过Handler给HandlerThreand发送要执行的任务。
        myThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                Log.e("Test", "Hello world1");
            }
        });
        myThreadHandler.post(new Runnable() {
            @Override
            public void run() {
                Log.e("Test", "Hello world2");
            }
        });
    }
}

从这个例子不难看出HandlerThread实际上是一个Thread,而这个Thread是负责处理Handler派发的消息和任务。此外值得注意有三点:

第一,只有一个线程来处理各种任务。

第一,执行的任务时有序的。也就是说顺序可以被控制。

第二,可以执行各种自定义的任务。

最后关于HandlerThread的退出:myThread.quit();

HandlerThread与SyncTask相比较,缺少执行过程的反馈。但是执行任务的多样性超过SyncTask。当然了都只启动了一个线程。

HandlerThread与Handler-Thread模式比较,也是缺少执行反馈。但是执行多任务时,HandlerThread却只需要一个线程。

 

所有的Handler就到这里了。也不经意间把SyncTask拿出来溜了一下。其他两篇

Handler 原理分析和使用(一)

Handler 原理分析和使用(二)

Handler完了。

posted @ 2016-08-06 15:30  欧颜柳  阅读(6454)  评论(0编辑  收藏  举报