前面已經提到過Handler的原理以及Handler的三種用法。這裏作一個很是簡單的一個總結:html
前兩篇文章使用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完了。