前一段時間跟着同學共同開發過幾個項目,但是那都是照搬別人的代碼,真正自己擼出來的代碼還是少數,就比如說現在要說的Handler,更多的是在需要使用的時候百度搜搜資料,或者是在《第一行代碼》上面直接拿來用,所以呢,感覺如果自己要進階的話,就不能這樣一直copy代碼,對待安卓的每一個知識點都要自己深刻解才行,這樣在以後的開發中纔會更加的得心應手,才能處理出現的各種問題。
首先來說說我對Handler的理解,Handler在辭典中的翻譯是處理者的意思,所以我們可以將它理解爲發送和處理消息的人,在Java中,你的每一個功能基本上都是通過某一個或者是某幾個方法來共同實現了,Handler的功能也不例外,發送消息一般都是通過sendMessage()來實現的,但是發出消息之後,最後又是怎麼能夠處理這個經過一理解加工處理之後的數據的呢?這裏Handler又提供了一個方法,handleMessage(),這個方法是用來最後接受上述數據的。Handler的主要原理就是上面的內容,內容不多,但是內部是怎麼個運行機制呢?在這裏要介紹一下安卓的異步消息處理機制,我們都知道,安卓內部是時時刻刻都運行着多線程的,多線程之間肯定要進行相應的信息交互,最爲典型的就是安卓不能在子線程中更新UI。上代碼:
public void onClick(View v) {
switch (v.getId()) {
case R.id.Click:
new Thread() {
// 重寫run()方法
public void run() {
click.setText("你點擊過了");
}
}.start();
break;
}
}
上面是onclick()方法中的代碼,再來看看xml文件中的代碼,這個比較簡單,就是定義一個控件即可
<Button
android:id="@+id/Click"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="點擊變換文字" />
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch
下圖是運行到模擬器上面的錯誤顯示,在點擊了按鈕之後,程序直接崩潰。
那麼上面的錯誤到底是如何產生的呢,,,最重要的原因是安卓並不是線程安全的,直觀的理解就是不能在子線程中更新UI,那麼如果我們需要在子線程中去執行一些耗時的任務,然後進行UI更新的時候我們該怎麼辦呢,這時候handler的作用就顯示出來了,如上所述,Handler就是用來進行線程之間的消息傳遞的,所以這裏我們可以將子線程中改變的信息通過Handler傳遞到主線程中就可以了,整個代碼貼出來
package com.example.handler;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewDebug.FlagToString;
import android.widget.Button;
public class MainActivity extends Activity implements OnClickListener {
private Button click;
public static final int Flag = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
click = (Button) findViewById(R.id.Click);
click.setOnClickListener(this);
}
// 創建一個Handler對象,用handleMessage()方法接收信息,最後在主線程中更新UI
private Handler handler = new Handler() {
public void handleMessage(Message message) {
switch (message.what) {
case Flag:
click.setText("你好,你點擊過我了");
break;
default:
break;
}
}
};
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.Click:
new Thread() {
// 重寫run()方法
public void run() {
/**
* new一個message對象 obtmessage
* 通過hangdler的sendmessage()方法將這個對象發送出去,然後在主線程中的Handler中接受數據
*/
Message obtMessage = new Message();
obtMessage.what = Flag;
handler.sendMessage(obtMessage);
}
}.start();
break;
}
}
}
很簡單的代碼,最終終於實現了想要的功能。探究安卓內部的運行機制,在安卓內部,有用於存放handler發送的消息,即消息隊列MessageQueue(),每次有需要用的信息,就直接通過調用Loop的loop()方法,就會將MessageQueue中的消息發送到handleMessage()方法中,然後判斷其的what字段,如上代碼所示,最後就能進行相應的操作,以上。