Android消息處理機制(Handler 與Message)---01

  1、handler的使用場景爲麼會有handler?(部份內容圖片摘自http://www.runoob.com/w3cnote/android-tutorial-handler-message.html)html

  

  2、handler的消息處理機制java

  在Android中提供了一種異步回調機制Handler,使用它,咱們能夠在完成一個很長時間的任務後作出相應的通知。android

  • UI線程:就是咱們的主線程,系統在建立UI線程的時候會初始化一個Looper對象,同時也會建立一個與其關聯的MessageQueue;
  • Handler:做用就是發送與處理信息,若是但願Handler正常工做,在當前線程中要有一個Looper對象
  • Message:Handler接收與處理的消息對象
  • MessageQueue:消息隊列,先進先出管理Message,在初始化Looper對象時會建立一個與之關聯的MessageQueue;
  • Looper:每一個線程只可以有一個Looper,管理MessageQueue,不斷地從中取出Message分發給對應的Handler處理!

  通俗一點講:當咱們的子線程想修改Activity中的UI組件時,咱們能夠新建一個Handler對象,經過這個對象向主線程發送信息;而咱們發送的信息會先到主線程的MessageQueue進行等待,由Looper按先入先出順序取出,再根據message對象的what屬性分發給對應的Handler進行處理!c++

  3、Handler的相關方法apache

  在使用android的消息的處理機制的時候:通常是有兩種手段,數組

  一、該message本身綁定到目標handler後,自行進入messageQueue,等待handler接受處理。Message方法:public static Message obtain(Handler h, int what, int arg1, int arg2, Object obj) ,經過該方法能夠得到一個消息:Message message = Message.obtain(handler, 33, 2, 3, "hello");網絡

發送消息的方式,有一點將本身綁定好了被髮射的感受,message.sendToTarget(); ---被動(意會)app

  二、handler主動設置要發送的消息的各個屬性值:arg1,arg2,obj,what。方法:public final Message obtainMessage(int what, int arg1, int arg2, Object obj) 經過該方法也能夠得到一個消息:好比Message message = handler.obtainMessage(3, 1, 2, "java");異步

而後將設置好的消息,由handler發送出去:handler.sendMessage(message);----主動(本身意會的)。下面十幾個經常使用方法:ide

  • void handleMessage(Message msg):處理消息的方法,使用handleMessage去處理消息,裏面的參數Message msg既是在messageQueue裏面取出的消息message~
  • sendEmptyMessage(int what):發送空消息
  • sendEmptyMessageDelayed(int what,long delayMillis):指定延時多少毫秒後發送空信息
  • sendMessage(Message msg):當即發送信息
  • sendMessageDelayed(Message msg):指定延時多少毫秒後發送信息
  • final boolean hasMessage(int what):檢查消息隊列中是否包含what屬性爲指定值的消息 若是是參數爲(int what,Object object):除了判斷what屬性,還須要判斷Object屬性是否爲指定對象的消息

//========================

 //廢話很少說直接上demo:由上圖中的圖2能夠看出消息的處理是在一條全新的線程中進行的,所以關鍵的是要新建一個thread,在它的run方法中執行消息的發送,

// 首先是被動方式:

 1 import android.os.Bundle;
 2 import android.os.Handler;
 3 import android.os.Message;
 4 import android.app.Activity;
 5 import android.view.View;
 6 import android.widget.Button;
 7 
 8 
 9 /**
10  * 此處重點熟悉message的屬性~,將message綁定到目標handler,而後直接使用message的方法將消息發送~,被動發送。
11  * @author 
12  * 
13  */
14 
15 // 在安卓開發中是絕對不能使用UI主線程去訪問網絡 的,必定是要開一條新的線程去訪問而後把結果返回
16 public class MainActivity extends Activity {
17     private Button button;
18 
19     // handler對象,用來接收消息~
20     private Handler handler = new Handler() {
21         @Override
22         public void handleMessage(android.os.Message msg) {  //這個是發送過來的消息
23             // 處理從子線程發送過來的消息
24             int arg1 = msg.arg1;  //獲取消息攜帶的屬性值
25             int arg2 = msg.arg2;
26             int what = msg.what;
27             Object result = msg.obj;
28             System.out.println("-arg1--->>" + arg1);
29             System.out.println("-arg2--->>" + arg2);
30             System.out.println("-what--->>" + what);
31             System.out.println("-result--->>" + result);
32             Bundle bundle = msg.getData(); // 用來獲取消息裏面的bundle數據
33             System.out.println("-getData--->>"
34                     + bundle.getStringArray("strs").length);
35         };
36     };
37 
38     @Override
39     protected void onCreate(Bundle savedInstanceState) {
40         super.onCreate(savedInstanceState);
41         setContentView(R.layout.activity_main);
42         button = (Button) findViewById(R.id.button1);
43 
44         button.setOnClickListener(new View.OnClickListener() {
45             @Override
46             public void onClick(View v) {
47                 // TODO Auto-generated method stub
48                 // 啓動一個子線程
49                 new Thread(new MyThread()).start();  //必定要在這裏面啓動!
50             }
51         });
52     }
53 
54     public class MyThread implements Runnable {
55         @Override
56         public void run() {   //run方法裏面寫要發送的消息對象,並對消息攜帶的信息進行定義!! 57             // TODO Auto-generated method stub
58 
59             // 第一種方式:獲取消息
60             // Message message = Message.obtain();
61             // message.what = 1;
62             // message.arg1 = 2;
63             // message.arg2 = 3;
64             // message.obj = "jack";
65             // handler.sendMessage(message);
66 
67             // 第二種方式
68             // Message message = Message.obtain(handler);
69             // message.what = 1;
70             // message.arg1 = 2;
71             // message.arg2 = 3;
72             // message.obj = "jack";
73             // //handler.sendMessage(message);
74             // //此時在構造方法裏面已經將message的target綁定了handler不須要再次發送了。
75             // message.sendToTarget();
76 
77             // 第三種方式,和上面是沒有區別的。。
78             // Message message = Message.obtain(handler, 33);
79             // message.arg1 = 2;
80             // message.arg2 = 3;
81             // message.obj = "jack";
82             // message.sendToTarget();
83 
84             // 第4種方式這幾種方式都是大同小異,只不過是內部封裝了而已,使用的時候根據實際須要就能夠了。
85             Message message = Message.obtain(handler, 33, 2, 3, "hello"); 86             Bundle data = new Bundle();  //message也能夠攜帶複雜一點的數據好比:bundle對象。
87             data.putStringArray("strs", new String[] { "c", "c++", "java" });
88             message.setData(data);
89             message.sendToTarget(); // 不可忘!
90         }
91     }
92 }

// ================================佈局文件就不給出了,就是一個按鈕而後爲該按鈕綁定了事件。

// =============================handler的主動發送消息

 

 1 import android.os.Bundle;
 2 import android.os.Handler;
 3 import android.os.Message;
 4 import android.os.SystemClock;
 5 import android.app.Activity;
 6 import android.view.Menu;
 7 import android.view.View;
 8 import android.view.View.OnClickListener;
 9 import android.widget.Button;
10 
11 /**
12  * 此處主要是使用handler的主動抓取發送message功能!在messaQequue裏面 13  * 
14  * @author15  * 
16  */
17 public class MainActivity extends Activity implements OnClickListener {
18     private Button button, button2;
19 
20     // Handler能夠接受發送消息,從消息隊列中提取消息用於更新UI,這裏都沒有對UI進行操做,主要是介紹如何定義本身的message如何發送這個message,最後將會給一個demo
21     private Handler handler = new Handler() {
22         @Override
23         public void handleMessage(android.os.Message msg) {
24 
25             System.out.println("-arg1--->" + msg.arg1);
26             System.out.println("-arg2--->" + msg.arg2);
27             System.out.println("-what--->" + msg.what);
28             System.out.println("-obj--->" + msg.obj);
29         };
30     };
31 
32     @Override
33     protected void onCreate(Bundle savedInstanceState) {
34         super.onCreate(savedInstanceState);
35         setContentView(R.layout.activity_main);
36         button = (Button) findViewById(R.id.button1);
37         button2 = (Button) findViewById(R.id.button2);
38 
39         button.setOnClickListener(this);
40         button2.setOnClickListener(this);
41     }
42 
43     @Override
44     public void onClick(View v) {
45         // TODO Auto-generated method stub
46         switch (v.getId()) {
47         case R.id.button1:
48             new Thread(new Runnable() {  //使用匿名內部類的方式,這個無難點吧。。。
49                 @Override
50                 public void run() {
51                     // TODO Auto-generated method stub
52                     // handler發送消息的第一種方式
53                     // handler.sendEmptyMessage(3);
54 
55                     // handler發送消息的第二種方式,第二個參數是指定在指定的時間上發送消息,這個是肯定的某個時間!
56                     // 能夠經過獲取當前的系統時間後SystemClock.uptimeMillis()再加上某個時間,若是給出的時間小於當前時間則當即發送,親測
             //並且感受這個功能很bug的,在特定的時間,須要咱們人爲的去計算:SystemClock.uptimeMillis()+myTime(這個是你想在多少毫秒後啓動的毫秒值)
57 // handler.sendEmptyMessageAtTime(3, X+3000); 59 // handler發送消息的第三種方式,這個效果是在3000毫秒後延遲。 60 // handler.sendEmptyMessageDelayed(3, 3000); 61 62 // handler發送消息的第四種方式 63 // Message message = Message.obtain(); //這個是使用message被動獲得 64 // Message message = handler.obtainMessage(); // 65 // handler的主動獲取消息,在源碼方面同樣!無區別。 66 // message.arg1 = 1; 67 // message.arg2 = 2; 68 // message.obj = "java"; 69 // message.what = 4; 70 // 使用handler發送消息的第五種方式,原理都是同樣的~
              //我最習慣仍是message本身搞本身的事情別去幹發送的活,message須要攜帶的屬性由他本身搞,剩下的發送接收處理的體力勞動由handler搞。
71 Message message = handler.obtainMessage(3, 1, 2, "java"); 72 handler.sendMessage(message); 73 } 74 }).start(); //記得啓動 75 break; 76 case R.id.button2: 77 // 第二個按鈕使用post方式發送消息,該方法須要一個runnable的實例,使用匿名內部類的方式實現。 78 // 直接使用一個匿名內部類Runnable來執行1.獲取消息對象;2.發送消息對象。換湯不換藥,經過看源碼也能夠知道背後的實現都是一個道理。 79 handler.post(new Runnable() { 80 @Override 81 public void run() { 82 // TODO Auto-generated method stub 83 Message message = handler.obtainMessage(23, 21, 22, "postMessage"); 84 handler.sendMessage(message); 85 } 86 }); 87 break; 88 } 89 } 90 91 }

//-----------------------------------具體應用handler來更新UI

//========================================

  2 
  3 import java.io.ByteArrayOutputStream;
  4 import java.io.IOException;
  5 import java.io.InputStream;
  6 
  7 import org.apache.http.HttpEntity;
  8 import org.apache.http.HttpResponse;
  9 import org.apache.http.client.HttpClient;
 10 import org.apache.http.client.methods.HttpGet;
 11 import org.apache.http.impl.client.DefaultHttpClient;
 12 import org.apache.http.util.EntityUtils;
 13 
 14 import android.os.Bundle;
 15 import android.os.Handler;
 16 import android.os.Message;
 17 import android.app.Activity;
 18 import android.app.ProgressDialog;
 19 import android.graphics.BitmapFactory;
 20 import android.view.View;
 21 import android.widget.Button;
 22 import android.widget.ImageView;
 23 
 24 public class MainActivity extends Activity {
 25     private Button button;
 26     private ImageView imageView;
 27     private String image_path = "http://www.deskcar.com/desktop/fengjing/200895150214/21.jpg";
 28     private final int IS_FINSIH = 1;
 29     private ProgressDialog dialog = null;
 30 
 31     // 標準的寫法
 32     private Handler handler = new Handler() {
 33         // 使用handleMessage去處理消息!!,裏面的參數Message msg既是發送過來的參數~
 34         @Override
 35         public void handleMessage(android.os.Message msg) {
 36             //
 37             // 在此接受發送過來的消息<---msg
 38             byte[] data = (byte[]) msg.obj;  //轉型
 39             // 將接受過來的數據賦值給imageview
 40             imageView.setImageBitmap(BitmapFactory.decodeByteArray(data, 0,
 41                     data.length));
 42             // 標記~數據發送已經結束了?,此處有由代碼的邏輯順序來決定的,
 43             if (msg.what == IS_FINSIH) {
 44                 dialog.dismiss();
 45             }
 46         };
 47     };
 48 
 49     @Override
 50     protected void onCreate(Bundle savedInstanceState) {
 51         super.onCreate(savedInstanceState);
 52         setContentView(R.layout.activity_main);
 53         imageView = (ImageView) findViewById(R.id.imageView1);
 54         dialog = new ProgressDialog(this);
 55         dialog.setTitle("提示");
 56         dialog.setMessage("正在下載,請稍等...");
 57         dialog.setCancelable(false);
 58 
 59         button = (Button) findViewById(R.id.button1);
 60         button.setOnClickListener(new View.OnClickListener() {
 61             @Override
 62             public void onClick(View v) {
 63                 // TODO Auto-generated method stub
 64                 // 開啓線程
 65                 new Thread(new MyThread()).start();
 66                 dialog.show(); // 顯示對話框他會直接先顯示出來這個是位於主線程裏面的。與thread互不影響。
 67 
 68             }
 69         });
 70     }
 71 
 72     // 避免在UI主線程裏面更新數據
 73     public class MyThread implements Runnable {
 74         @Override
 75         public void run() {
 76             // TODO Auto-generated method stub
 77             // 使用http完成網絡下載的操做
 78             HttpClient httpClient = new DefaultHttpClient();
 79             HttpGet httpGet = new HttpGet(image_path);
 80             HttpResponse httpResponse = null;
 81             //下面是我在http的使用過程當中總結的一些心得,對於http沒有經驗,有錯請指出。。。
 82             /*
 83              * 這種方式獲取響應內容的實體~entity中的流對象!不建議使用了。比較麻煩, InputStream inputStream
 84              * =null; inputStream = httpResponse.getEntity().getContent();
 85              * 而後將該inputStream寫入到ByteArrayOutputStream,而後該內存緩衝流能夠轉爲字節數組byte[]=
 86              * outputStream.toByteArray();
 87              */
 88             // 使用http新的就是經過httpclient執行要執行的get/或者post方法而後獲取服務端響應過來的實體對象entity;
 89             // 而後從該entity中獲取須要的數據好比inputstream/文件的長度等。。。通常咱們的最終目的都是獲取一個字節數組!byte[]只有二進制的數據纔是數據的終極形態!
 90             // 在使用的時候爲了方便操做有一個工具類能夠幫助咱們簡單的獲取二進制數組
 91             try {
 92                 httpResponse = httpClient.execute(httpGet);// client執行請求~典型的面對對象:客戶端對象取執行請求的方法,得到返回的內容對象。經過工具來解析內容  93                 // 判斷鏈接是否正常
 94                 if (httpResponse.getStatusLine().getStatusCode() == 200) {
 95 
 96                     HttpEntity entity = httpResponse.getEntity();  //獲取響應頭的實體內容
 97                     // 使用EntityUtils
 98                     byte[] data = EntityUtils.toByteArray(entity);
 99                     // 到了這裏就是須要把咱們的數據發送給UI主線程,二進制數組是最好的發送對象!!!
100                     // Message message = new Message() 該方法是建立而不是在的當前的線程池取出。
101                     Message message = Message.obtain();
102                     message.obj = data;
103                     message.what = IS_FINSIH; // 結束標誌位
104                     handler.sendMessage(message); // 將數據發送過去~
105                 }
106 
107             } catch (IOException e) {
108                 // TODO Auto-generated catch block
109                 e.printStackTrace();
110             }
111         }
112     }
113 }

 ---------------若有侵犯,請告知。

相關文章
相關標籤/搜索