Handler 原理分析和使用之HandlerThread

前面已經提到過Handler的原理以及Handler的三種用法。這裏作一個很是簡單的一個總結:html

  • Handler 是跨線程的Message處理。負責把Message推送到MessageQueue和處理。
  • Looper 用來輪詢MessageQueue,獲取Message 發送給指定的Handler進行處理。
  • Looper 須要和線程綁定,綁定那個線程,Handler就會在那個線程處理Message

前兩篇文章使用Handler處理的場景是:主線程(UI線程)被子線程更新。即便用主線程的Handler和Looper,在子線程中發Message。而後主線程處理 handlerMessage。java

-----------------------------------------------------------------------------------------android

下面反過來講,如何從UI線程發消息,讓子線程處理。多線程

最爲一般的作法是:new Thread().start。起一個線程去完成一個任務,任務完成線程就能夠自斃了。固然了若是不須要子線程返回結果,並且只有一個線程,那麼這是最簡單的了。app

另外一種方法是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不但能夠給主線程提供啓動和中止接口,還能夠給主線程上報過程。固然了開銷也是有的。ide

實際上這種方式也能夠用 Handler 原理分析和使用(一)中的例子實現。oop

 

以上都是主線程啓動一個子線程完成任務。可是若是要作多個異步任務,該如何實現?post

首先,從多個異步任務來考慮,若是仍是各自不一樣的話,先考慮到的是線程池。這個在後面的多線程部分在說明。ui

還有一種方式就是使用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完了。

相關文章
相關標籤/搜索