在上篇 Handler 原理分析和使用(一)中,介紹了一個使用Handler的一個簡單而又常見的例子,這裡還有一個例子,當然和上一篇的例子截然不同,也是比較常見的,實例如下。 實際運行這個例子,點擊Button之後,TextView文字內容會變成“I get Post Message”。為什麼會是這 ...
在上篇 Handler 原理分析和使用(一)中,介紹了一個使用Handler的一個簡單而又常見的例子,這裡還有一個例子,當然和上一篇的例子截然不同,也是比較常見的,實例如下。
1 import android.os.Handler; 2 import android.os.Looper; 3 import android.os.Message; 4 import android.os.MessageQueue; 5 import android.support.v7.app.AppCompatActivity; 6 import android.os.Bundle; 7 import android.view.View; 8 import android.widget.Button; 9 import android.widget.TextView; 10 11 public class MainActivity extends AppCompatActivity implements View.OnClickListener{ 12 13 private TextView myTextView; 14 private Button myButton; 15 private Handler myHandler; 16 @Override 17 protected void onCreate(Bundle savedInstanceState) { 18 super.onCreate(savedInstanceState); 19 setContentView(R.layout.activity_main); 20 myHandler = new Handler(); 21 myTextView = (TextView)this.findViewById(R.id.text_view); 22 myButton = (Button)this.findViewById(R.id.post); 23 myButton.setOnClickListener(this); 24 } 25 26 @Override 27 public void onClick(View view) { 28 int id = view.getId(); 29 if(id == R.id.post){ 30 Runnable updateUI = new Runnable() { 31 @Override 32 public void run() { 33 myTextView.setText("I get Post Message"); 34 } 35 }; 36 //將該線程發送到主線程運行 37 myHandler.post(updateUI); 38 } 39 } 40 }
實際運行這個例子,點擊Button之後,TextView文字內容會變成“I get Post Message”。為什麼會是這樣,我們從源碼開始著手查看。
先看Handler的post(Runnable)方法(post還有幾個姊妹方法,這裡不再一一論述,都是殊途同歸)。源碼如下:
1 public final boolean post(Runnable r) 2 { 3 return sendMessageDelayed(getPostMessage(r), 0); 4 }
調用了sendMessageDelayed(...), 先看getPostMessage(r),源碼如下:
1 private static Message getPostMessage(Runnable r) { 2 //獲取消息池中的一個消息 3 Message m = Message.obtain(); 4 //將Runnable作為消息的callback 5 m.callback = r; 6 return m; 7 }
在看sendMessageDelayed(Message,int)的源碼:(在Handler 原理分析和使用(一)中有說明)
1 public final boolean sendMessageDelayed(Message msg, long delayMillis) 2 { 3 if (delayMillis < 0) { 4 delayMillis = 0; 5 } 6 return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); 7 } 8 public boolean sendMessageAtTime(Message msg, long uptimeMillis) { 9 MessageQueue queue = mQueue; 10 if (queue == null) { 11 RuntimeException e = new RuntimeException( 12 this + " sendMessageAtTime() called with no mQueue"); 13 Log.w("Looper", e.getMessage(), e); 14 return false; 15 } 16 return enqueueMessage(queue, msg, uptimeMillis); 17 } 18 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { 19 //綁定Handler 20 msg.target = this; 21 if (mAsynchronous) { 22 msg.setAsynchronous(true); 23 } 24 //將Message推入MessageQueue 25 return queue.enqueueMessage(msg, uptimeMillis); 26 }
實際上和sendMessage(Message)一樣的流程。當然了緊接著Looper.loop()。然後調用到dispatchMessage(Message) 該方法需要在此重新說明。看源碼:
1 public void dispatchMessage(Message msg) { 2 if (msg.callback != null) { 3 //如果message的callback不為空,則 4 handleCallback(msg); 5 } else { 6 7 if (mCallback != null) { 8 //如果Handler的callback不為空,則 9 if (mCallback.handleMessage(msg)) { 10 return; 11 } 12 } 13 //處理Message 14 handleMessage(msg); 15 } 16 }
在進入handleCallback(Message)方法查看源碼:
1 private static void handleCallback(Message message) { 2 //直接執行run方法 3 message.callback.run(); 4 }
註意,此時message已經是主線程對象。因此調用run方法就是在主線程中運行。
此外還需要註意,runnable要處理的內容會在主線程中處理,因此不能夠占用太多的時間,從而造成ANR。
--------------------------------------------------------------------------------------------
之所以用一條線隔開,是因為還有一個實例需要說明。請註意dispatchMessage(message)裡面的這段代碼:
if (mCallback != null) { //如果Handler的callback不為空,則 if (mCallback.handleMessage(msg)) { return; } }
這個mCallback是從哪裡來,這個有引出Handler的另一個使用方法。
首先來看Handler的初始化方法,有一下幾個:
1. publicHandler()
2. publicHandler(Callback)
3. publicHandler(Looper)
4. publicHandler(Looper, Callback)
第1,3個一眼看去就明白。第4個只要明白第2個也就通了。
關鍵點,Callback是什麼?是一個介面。源碼如下:
1 public interface Callback { 2 public boolean handleMessage(Message msg); 3 }
該介面實際上是要求實現handleMessage(Message)方法,相信這個方法大家都不陌生。
再看該初始化方法:
1 Handler handler = new Handler(new Handler.Callback() { 2 @Override 3 public boolean handleMessage(Message msg) { 4 return false; 5 } 6 });
這裡已經很明顯了。就是重新定義了handleMessage方法。那麼在dispatchMessage方法中如果發現mCallback不為空,則所有的消息都執行該Callback定義的handleMessage(Message).
具體的例子不想寫了。今天就到這裡吧。太累了。明天不在深入,而是擴展。