Handler背景理解: Handler被最多的使用在了更新UI線程中,但是,這個方法具體是什麼樣的呢?我在這篇博文中先領著大家認識一下什麼是handler以及它是怎麼樣使用在程式中,起著什麼樣的作用。 示例說明: 首先先建立兩個按鈕:一個是start按鈕,作用是開啟整個程式。另一個是終止按鈕end ...
Handler背景理解:
Handler被最多的使用在了更新UI線程中,但是,這個方法具體是什麼樣的呢?我在這篇博文中先領著大家認識一下什麼是handler以及它是怎麼樣使用在程式中,起著什麼樣的作用。
示例說明:
首先先建立兩個按鈕:一個是start按鈕,作用是開啟整個程式。另一個是終止按鈕end,作用是結束整個的程式。這兩個按鈕的相互對比就會讓大家明白Handlerd的基本的工作原理。
運行結果截圖:
MainActivity.class
package com.example.testhandler; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private Button start,end; //實例化一個handler對象 private Handler handler = new Handler(); //開啟一個新的線程:開啟線程有兩種方式,一種是使用普通的Thread方法,另一個中是使用Runnable方法 Runnable update = new Runnable() { @Override public void run() { System.out.println("update"); handler.postDelayed(update, 3000); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); start = (Button)this.findViewById(R.id.btn_start); end = (Button)this.findViewById(R.id.btn_end); start.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //加入到隊列中去執行 handler.post(update); } }); end.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { //將消息移除隊列中去 handler.removeCallbacks(update); } }); } }
當點擊Start按鈕時的效果圖如下:
當點擊end按鈕時的效果圖如下:
註意:
Handler中的post方法並沒有開啟一個新的線程,他的操作是在主線程中執行的。下麵咱們就來驗證一下這個觀點。
首先先貼一下運行截圖:
等過10s之後的運行結果是:
這裡只是測試一下handler的post()方法是否是在主線程中進行的。所以沒有佈局。
設計思路:
在主線程中輸出主線程當前的ID和Name,然後使用Runnable方式新建一個線程,在這個新線程中讓程式睡眠10s,將這個線程使用Handler的post()方法發送到主線程中,看是否是執行非同步載入。也就是驗證handler是否是非同步載入方式。結論:Handler不是非同步載入方式。
MainActivity:
package com.example.handlertest1; import android.os.Bundle; import android.os.Handler; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { private Handler mhandler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //將多線程發送到消息隊列中 mhandler.post(r); //不會立刻載入界面,這說明瞭handler並不是開闢了一個新的線程而是在主線程中進行的。 setContentView(R.layout.activity_main); System.out.println("Activity-->"+Thread.currentThread().getId()); System.out.println("Activity-->"+Thread.currentThread().getName()); } Runnable r = new Runnable() { public void run() { System.out.println("Handler--->"+Thread.currentThread().getId()); System.out.println("handler--->"+Thread.currentThread().getName()); try { Thread.sleep(10000); } catch (Exception e) { e.printStackTrace(); } } }; }
LogCat文件的輸出:
在這裡通過ID號很明顯的看出這不是執行的是多線程載入
在上面的主線程中重新新建一個線程則實現了多線程的載入:
將上面的onCreate()中的代碼替換為:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //將多線程發送到消息隊列中 // mhandler.post(r); //不會立刻載入界面,這說明瞭handler並不是開闢了一個新的線程而是在主線程中進行的。 setContentView(R.layout.activity_main); //這是另外開啟了一個新的線程,會發現這裡輸出的速率會比上次的快很多 Thread t = new Thread(r); t.start(); System.out.println("Activity-->"+Thread.currentThread().getId()); System.out.println("Activity-->"+Thread.currentThread().getName()); }
效果截圖如下:
LogCat文件中的輸出結果截圖為:
在這裡通過ID號很明顯的看出了這是執行了多線程載入。
Handler要想開闢一個新的線程需要使用HanderThread()方法。下麵就是HandlerThread()的用法:
設計思路:
通過使用handler方法傳輸數據,然後使用HandlerThread,實現了使用Looper來處理消息隊列的功能。輸出當前的Activity的ID和Name,以及Handler的ID和Name以及傳輸的數據
代碼如下:
1 package com.example.handlertest1; 2 3 import android.app.Activity; 4 import android.os.Bundle; 5 import android.os.Handler; 6 import android.os.HandlerThread; 7 import android.os.Looper; 8 import android.os.Message; 9 10 public class HandlerTest2 extends Activity{ 11 12 @Override 13 protected void onCreate(Bundle savedInstanceState) { 14 super.onCreate(savedInstanceState); 15 setContentView(R.layout.activity_main); 16 17 //列印當前線程的ID和當前線程的名字 18 System.out.println("Activity-->"+Thread.currentThread().getId()); 19 System.out.println("Activity-->"+Thread.currentThread().getName()); 20 21 //HandlerThread是以鍵值對的形式進行存儲的,這裡的handler_thread就是該handler的鍵名 22 //生成一個HandlerThread對象,實現了使用Looper來處理消息隊列的功能。這是有android來提供的並不是java中的Thread提供 23 HandlerThread handlerthread = new HandlerThread("handler_thread"); 24 handlerthread.start(); 25 MyHandler myhandler = new MyHandler(handlerthread.getLooper()); 26 Message msg = myhandler.obtainMessage(); 27 //傳送多的數據的時候使用的setData()方法,使用Bundle()將數據包裝 28 Bundle b = new Bundle(); 29 b.putInt("age", 20); 30 b.putString("name", "張三"); 31 msg.setData(b); 32 //將消息發送給目標,目標就是生成該msg對象的handler 33 msg.sendToTarget(); 34 35 } 36 37 class MyHandler extends Handler{ 38 39 public MyHandler(){ 40 41 } 42 public MyHandler(Looper looper){ 43 super(looper); 44 } 45 46 @Override 47 public void handleMessage(Message msg) { 48 Bundle b = msg.getData(); 49 int age = b.getInt("age"); 50 String name = b.getString("name"); 51 System.out.println("age is"+age+",name"+name); 52 System.out.println("Handler--->"+Thread.currentThread().getId()); 53 System.out.println("Handler--->"+Thread.currentThread().getName()); 54 System.out.println("handlermessage"); 55 } 56 57 } 58 59 }
好了,就這麼多了,具體的關於Handler、Looper、Message三者的關係,參考http://blog.csdn.net/lmj623565791/article/details/38377229個人感覺不錯