1、Handler機制是Android提供的一種異步回調機制,在Ui線程中使用handler需要new一個handler對象,並重寫其中的handleMessage(Message msg)方法,處理如更新UI等操作。
private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { //to do } };
然后在異步線程中調用hanlder.sendMessage(Message msg)告訴UI線程去更新UI等操作。
從原理上來講,使用了Hanlder對象的線程需要綁定一個Looper對象,該對象維護一個消息隊列,Looper對象取出該隊列的消息后交由handler進行處理。所以在使用Handler時,要調用Looper.prepare()方法給當前的線程綁定一個Looper對象。
public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }
然后調用loop()建立對消息隊列的循環,在消息隊列中取出消息后交由相應的handler進行處理。由於一個線程中可能有多個handler,為了區分這些不同的hanlder所需要處理的消息,每個Message對象都維護有一個hanlder實例即target,在loop方法中通過調用msg.target.dispatchMessage(msg)進行處理。
每個線程只能綁定一個loop對象,多個handler共享,handler的在構造時從當前的線程中取得loop對象,Looper中的myLooper中返回了sThreadLocal.get()所取得的Looper對象
mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue;
所以,在使用handler中需要執行以下步驟,首先調用Looper.prepare()方法為當前線程綁定Looper對象,然后才可以實例化一個Handler對象,最后調用loop()方法建立消息循環
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
在很多情況下我們在activity或者其他場合中使用Handler進行異步消息處理,並沒有顯式地聲明綁定一個Looper對象。這是因為主線程它已經綁定了一個Looper對象
public static final void main(String[] args) { SamplingProfilerIntegration.start(); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper(); ActivityThread thread = new ActivityThread(); thread.attach(false); Looper.loop(); if (Process.supportsProcesses()) { throw new RuntimeException("Main thread loop unexpectedly exited"); } thread.detach(); String name = (thread.mInitialApplication != null) ? thread.mInitialApplication.getPackageName() : "<unknown>"; Slog.i(TAG, "Main thread of " + name + " is now exiting"); }