接上篇文章《安卓開發筆記——關于AsyncTask的使用》,今天來講下在安卓開發里"重中之重"的另一個異步操作類Handler。
今天打算先講下關于Handler的一些基本定義和使用方式
還是以一個下載圖片為例,先看下實例效果:

好了,先來看下關于Handler的定義:

以上是官方對于Hanler類的描述,大致意思是說:Handler主要用于異步消息的處理:當發出一個消息之后,首先進入一個消息隊列,發送消息的函數即刻返回,而另外一個部分在消息隊列中逐一將消息取出,然后對消息進行處理,也就是發送消息和接收消息不是同步的處理。 這種機制通常用來處理相對耗時比較長的操作。
1、Handler是一套更新UI的機制,在子線程中進行耗時操作,然后通過它來通知主線程對UI進行更新。
2、Handler也是一套消息處理機制,可以用它來發送消息和處理消息。
關于Handler的用途:

Handler可以分發Message對象和Runnable對象到主線程中,每個Handler的實例都會綁定到創建他的線程中(一般是位于主線程)
用途:1、安排消息或Runnable 在某個主線程中某個地方執行 2、安排一個動作在不同的線程中執行
接下來講講Handler的基本使用方式,今天先不講太復雜,不引入線程和消息隊列的概念,等下篇文章來說。
先來個教科書版本的Handler使用方式:(注釋很全)
1 package com.example.handlertest_01; 2 3 import java.io.IOException; 4 5 import org.apache.http.HttpEntity; 6 import org.apache.http.HttPResponse; 7 import org.apache.http.client.ClientProtocolException; 8 import org.apache.http.client.HttpClient; 9 import org.apache.http.client.methods.HttpGet;10 import org.apache.http.impl.client.DefaultHttpClient;11 import org.apache.http.util.EntityUtils;12 13 import android.app.Activity;14 import android.app.ProgressDialog;15 import android.graphics.Bitmap;16 import android.graphics.BitmapFactory;17 import android.os.Bundle;18 import android.os.Handler;19 import android.os.Message;20 import android.view.View;21 import android.view.View.OnClickListener;22 import android.widget.Button;23 import android.widget.ImageView;24 25 public class MainActivity extends Activity {26 //聲明所使用控件27 private ImageView imageView;28 private Button button;29 private ProgressDialog progressDialog;30 private String path = "http://pic.baomihua.com/photos/201110/m_6_634545730007187500_16585344.jpg";//下載圖片的資源地址31 32 //創建一個Handler對象33 private Handler handler = new Handler() {34 public void handleMessage(android.os.Message msg) {35 byte[] data=(byte[]) msg.obj;//直接obj對象36 Bitmap bitmap=BitmapFactory.decodeByteArray(data, 0, data.length);37 progressDialog.dismiss();38 imageView.setImageBitmap(bitmap);39 };40 };41 42 @Override43 protected void onCreate(Bundle savedInstanceState) {44 super.onCreate(savedInstanceState);45 setContentView(R.layout.activity_main);46 //對控件進行實例化,并設置相對應屬性47 imageView = (ImageView) findViewById(R.id.imageView);48 button = (Button) findViewById(R.id.bt);49 progressDialog=new ProgressDialog(this);50 progressDialog.setTitle("當前任務");51 progressDialog.setMessage("正在下載圖片,請稍后..");52 53 //給按鈕綁定監聽54 button.setOnClickListener(new OnClickListener() {55 56 @Override57 public void onClick(View v) {58 progressDialog.show();59 new Thread(new MyThread()).start();//開辟一條子線程,執行該線程操作60 }61 });62 63 }64 65 // 繼承Runnable接口,開辟新線程訪問網絡資源66 public class MyThread implements Runnable {67 @Override68 public void run() {69 HttpClient httpClient = new DefaultHttpClient();70 HttpGet httpGet = new HttpGet(path);71 try {72 HttpResponse httpResponse = httpClient.execute(httpGet);73 if (httpResponse.getStatusLine().getStatusCode() == 200) {74 // 訪問成功75 HttpEntity entity = httpResponse.getEntity();76 // 阿帕奇提供的工具類EntityUtils可以很方便的把實體對象轉換成字節碼數組77 byte[] data = EntityUtils.toByteArray(entity);78 79 Message message = handler.obtainMessage();//取得Message消息對象80 message.obj = data;81 handler.sendMessage(message);//利用handler發送消息82 }83 } catch (ClientProtocolException e) {84 e.printStackTrace();85 } catch (IOException e) {86 e.printStackTrace();87 }88 }89 90 }91 92 }
這里的Message就是上文所提到的消息,這邊有個特別需要主要的是如何得到一個Message的實例對象,官方不提倡我們直接new Message(),它提供了很多種方法讓我們去獲取,具體我們可以看下API文檔:
Handler類:

Message類:

為什么不直接去new Message()對象,查看過源碼的朋友可以發現,其實Message.obtain()或者是Handler.obtainMesssage()在源碼里我們可以發現,Android給我們提供了一個消息池,這個消息池的大小為50而且加鎖了,在我們調用這些方法的時候,系統會先去消息池里去取消息對象,如果不存在那么它才會去new出一個新的Message消息對象。
Message源代碼:

以上API這里再列舉一個:
1 Message message=Message.obtain(handler);2 message.obj=data;3 message.sendToTarget();
都很簡單,大家參照著API給的規范去做就可以了。
Message對象,里面除了給我們提供了obj這個存儲對象之外,它還幫我們提供了一些其他類型的存儲變量,比如:

這幾個變量都是Android給我們提供的輕消耗的變量,我們可以拿來用,例如arg1,arg2我們可以用來存放簡單的整型變量,what我們可以用來存放消息的標識符,然后在handMessgae(Message msg)里用一個switch去判斷要執行那些操作等等,用法和上面給的代碼一致。
具體大家查看下API結合我剛給的注釋,其實都很簡單,這里就不一一舉例了。
最后再看看下幾個發送消息的API:

說幾個易混淆的吧,其他的大家可以自己嘗試玩玩
比如sendMessageDelayed是延遲發送回消息,后面跟著long類型的時間,以毫秒為單位。
還有sendMessAtTime是定時發送消息,時間由uptimeMills()傳遞
這兩句是等效的,都是延時1秒將消息加入列隊:
1 handler.sendMessageAtTime(msg, SystemClock.uptimeMillis()+1000);2 handler.sendMessageDelayed(msg, 1000);
好了,先介紹這么多吧,其他的等下篇文章再說。
新聞熱點
疑難解答