Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中的Handler

Android中的Handler

編輯:關於Android編程

當我們在處理下載或是其他需要長時間執行的任務時,如果直接把處理函數放在Activity的OnCreate或是OnStart中,會導致執行過程中整個Activity無響應,如果時間過長,程序就會掛掉。Handler就是把這些功能放到一個當初的線程裡執行,與Activity互不影響。

一、Handler的定義:
  Handler主要接收子線程發送的數據, 並用此數據配合主線程更新UI,用來跟UI主線程交互用。比如可以用handler發送一個message,然後在handler的線程中來接收、處理該消息,以避免直接在UI主線程中處理事務導致影響UI主線程的其他處理工作,Android提供了Handler作為主線程和子線程的紐帶;也可以將handler對象傳給其他進程,以便在其他進程中通過handler給你發送事件;還可以通過handler的延時發送message,可以延時處理一些事務的處理。

  解釋:當應用程序啟動時,Android首先會開啟一個主線程 (也就是UI線程) , 主線程為管理界面中的UI控件,進行事件分發。比如說,你要是點擊一個button,android會分發事件到button上,來影響你的操作。如果此時需要一個耗時的操作,例如:聯網讀取數據,或者讀取本地較大的一個文件的時候,你不能把這些操作放在主線程中,如果你放在主線程中的話,界面會出現假死現象,如果5秒鐘還沒有完成的話,會收到Android系統的一個錯誤提示"強制關閉". 這個時候我們需要把這些耗時的操作,放在一個子線程中,因為子線程涉及到UI更新,但是當子線程中有涉及到操作UI的操作時,就會對主線程產生危險,也就是說,更新UI只能在主線程中更新,在子線程中操作是危險的. 這個時候,Handler就出現了,來解決這個復雜的問題,由於Handler運行在主線程中(UI線程中),它與子線程可以通過Message對象來傳遞數據,這個時候,Handler就承擔著接受子線程傳過來的(子線程用sedMessage()方法傳遞)Message對象,(裡面包含數據), 把這些消息放入主線程隊列中,配合主線程進行更新UI。

二、Handler一些特點

handler可以分發Message對象和Runnable對象到主線程中, 每個Handler實例,都會綁定到創建他的線程中(一般是位於主線程), 也就是說Handler對象初始化後,就默認與對它初始化的進程的消息隊列綁定,因此可以利用Handler所包含的消息隊列,制定一些操作的順序。

它有兩個作用: (1): 安排消息或Runnable 在某個主線程中某個地方執行, (2)安排一個動作在不同的線程中執行

Handler中分發消息的一些方法

post(Runnable)

postAtTime(Runnable,long)

postDelayed(Runnablelong)

post類方法允許你排列一個Runnable對象到主線程隊列中

sendEmptyMessage(int)

sendMessage(Message)

sendMessageAtTime(Message,long)

sendMessageDelayed(Message,long)

sendMessage類方法, 允許你安排一個帶數據的Message對象到隊列中

三、handler的簡單工作原理圖

\

四、應用實例:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHA+ICAgMaOstKu13U1lc3NhZ2Who9PD09q908rc19PP37PMt6LLzbXEyv2+3SwgsqLTw7TLyv2+3cXkus/W98/fs8y4/NDCVUmhozwvcD4KPHA+ICAgICAgICAgINTaQW5kcm9pZNbQo6y21NPaVUm1xLLZ1/fNqLOj0OjSqrfF1NrW98/fs8zW0L340NCy2df3oaPI57n71NrX08/fs8zW0NPQudjT2lVJtcSy2df3o6zEx8O0vs3Q6NKqsNHK/b7dz/vPotf3zqrSu7j2TWVzc2FnZbbUz/O3osvNtb3P+8+ittPB0NbQo6zIu7rzo6zTw0hhbmRsZXLW0LXEaGFuZGxlck1lc3NnZbe9t6i0psDttKu5/cC0tcTK/b7d0MXPoqOssqKy2df3VUmho8Dgc2VuZE1lc3NhZ2UoTWVzc2FnZW1zZym3vbeoyrXP1reiy83P+8+itcSy2df3oaMg1Nqz9cq8u69IYW5kbGVyttTP88qx1tjQtLXEaGFuZGxlTWVzc2FnZbe9t6jAtL3TytVNZXNzZ2FlsqK9+NDQz+C52LLZ1/ehozwvcD4KPHA+ICAyo6y0q7XdUnVubmFibGW21M/zoaPTw9Pazai5/UhhbmRsZXKw87aotcTP+8+ittPB0KOssLLFxbK7zayy2df3tcTWtNDQy7PQ8qGjPC9wPgo8cD5IYW5kbGVyttTP89TavfjQ0LP1yry7r7XEyrG68qOsu+HErMjPtcTX1LavsPO2qM/7z6K208HQoaPA+9PDwOBwb3N0t723qKOsv8nS1L2rUnVubmFibGW21M/zt6LLzbW9z/vPorbTwdDW0KOssLTV1bbTwdC1xLv61sawtMuz0PLWtNDQsrvNrLXEUnVubmFibGW21M/z1tC1xHJ1bre9t6ihozwvcD4KPHA+we3N4qOsQW5kcm9pZLXEQ1BVt9bF5LXE1+7QobWl1KrKx8/fs8yjrEhhbmRsZXLSu7DjysfU2sSzuPbP37PMwO+0tL2otcSjrNLytvhIYW5kbGVyus1UaHJlYWS+zcrHz+C7pbDztqi1xKOs0rvSu7bU06aho7b4UnVubmFibGXKx9K7uPa907/ao6xUaHJlYWTKx1J1bm5hYmxltcTX08DgoaPL+dLUy7WjrMv7wam2vMvj0ru49r34s8yhozwvcD4KPHA+PGJyPgo8L3A+CjxwPjxicj4KPC9wPgo8cD5tYXJzX2FuZHJvaWRzytPGtdbQtcS0+sLrPC9wPgo8cD48cHJlIGNsYXNzPQ=="brush:java;">package mars.handler; 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 HandlerActivity extends Activity { /** Called when the activity is first created. */ //聲明兩個按鈕控件 private Button startButton = null; private Button endButton = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //根據控件的ID得到代表控件的對象,並未這兩個按鈕設置相應的監聽器 startButton = (Button)findViewById(R.id.startButton); startButton.setOnClickListener(new StartButtonListener()); endButton = (Button)findViewById(R.id.endButton); endButton.setOnClickListener(new EndButtonListener()); } class StartButtonListener implements OnClickListener{ @Override public void onClick(View v) { //調用Handler的post方法,將要執行的線程對象添加到隊列當中 handler.post(updateThread); } } class EndButtonListener implements OnClickListener{ @Override public void onClick(View v) { handler.removeCallbacks(updateThread); } } //創建一個Handler對象 Handler handler = new Handler(); //將要執行的操作寫在線程對象的run方法當中 Runnable updateThread = new Runnable(){ @Override public void run() { System.out.println("UpdateThread"); //在run方法內部,執行postDelayed或者是post方法 handler.postDelayed(updateThread, 3000); } }; }

程序的運行結果就是每隔3秒鐘,就會在控制台打印一行UpdateTread。這是因為實現了Runnable接口的updateThread對象進入了空的消息隊列即被立即執行run方法,而在run方法的內部,又在3000ms之後將其再次發送進入消息隊列中。


3.Handler和多線程

post方法雖然發送的是一個實現了Runnable接口的類對象,但是它並非創建了一個新線程,而是執行了該對象中的run方法。也就是說,整個run中的操作和主線程處於同一個線程。

這樣對於那些簡單的操作,似乎並不會影響。但是對於耗時較長的操作,就會出現“假死”。為了解決這個問題,就需要使得handler綁定到一個新開啟線程的消息隊列上,在這個處於另外線程的上的消息隊列中處理傳過來的Runnable對象和消息

package mars.handler;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;

public class HandlerTest2 extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		//打印了當前線程的ID
		System.out.println("Activity-->" + Thread.currentThread().getId());
		//生成一個HandlerThread對象,實現了使用Looper來處理消息隊列的功能,這個類由Android應用程序框架提供
		HandlerThread handlerThread = new HandlerThread("handler_thread");
		//在使用HandlerThread的getLooper()方法之前,必須先調用該類的start();
		handlerThread.start();
		//將由HandlerThread獲取的Looper傳遞給Handler對象,即由處於另外線程的Looper代替handler初始化時默認綁定的消息隊列來處理消息。  
                // HandlerThread顧名思義就是可以處理消息循環的線程,它是一個擁有Looper的線程可以處理消息循環;  
                //其實與其說Handler和一個線程綁定,倒不如說Handler和Looper是一一對應的。
		MyHandler myHandler = new MyHandler(handlerThread.getLooper());
		Message msg = myHandler.obtainMessage();
		//將msg發送到目標對象,所謂的目標對象,就是生成該msg對象的handler對象
		Bundle b = new Bundle();
		b.putInt("age", 20);
		b.putString("name", "Jhon");
		msg.setData(b);
		msg.sendToTarget();
	}
	
	class MyHandler extends Handler{
		public MyHandler(){
			
		}
		public MyHandler(Looper looper){
			super(looper);
		}
		@Override
		public void handleMessage(Message msg) {
			Bundle b = msg.getData();
			int age = b.getInt("age");
			String name = b.getString("name");
			System.out.println("age is " + age + ", name is" + name);
			System.out.println("Handler--->" + Thread.currentThread().getId());
			System.out.println("handlerMessage");
		}
	}
}

這樣,當使用sendMessage方法傳遞消息或者使用post方法傳遞Runnable對象時,就會把它們傳遞到與handler對象綁定的處於另外一個線程的消息隊列中,它們將在另外的消息隊列中被處理。而主線程還會在發送操作完成時候繼續進行,不會影響當前的操作。

這裡需要注意,這裡用到的多線程並非由Runnable對象開啟的,而是ThreadHandler對象開啟的。Runnable對象只是作為一個封裝了操作的對象被傳遞,並未產生新線程。

在UI線程(主線程)中:

mHandler=newHandler();

mHandler.post(newRunnable(){

void run(){

//執行代碼..

}

});

這個線程其實是在UI線程之內運行的,並沒有新建線程。

常見的新建線程的方法是:

Thread thread = newThread();

thread.start();

HandlerThreadthread = new HandlerThread("string");

thread.start();





  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved