Handler 原理分析和使用(二)_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > Handler 原理分析和使用(二)

Handler 原理分析和使用(二)

 2016/8/5 5:30:56  欧颜柳  程序员俱乐部  我要评论(0)
  • 摘要:在上篇Handler原理分析和使用(一)中,介绍了一个使用Handler的一个简单而又常见的例子,这里还有一个例子,当然和上一篇的例子截然不同,也是比较常见的,实例如下。1importandroid.os.Handler;2importandroid.os.Looper;3importandroid.os.Message;4importandroid.os.MessageQueue;5importandroid.support.v7.app.AppCompatActivity
  • 标签:使用 Handler 分析

在上篇 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).

 

具体的例子不想写了。今天就到这里吧。太累了。明天不在深入,而是扩展。

发表评论
用户名: 匿名