Handler 机制

Handler 机制

Android事件机制详细解读

Android中的Handler的机制与用法详解

1. 什么是Handler ,它是干什么用?使用场景有哪些?

1.1 Handler 的概念

在 Android 中提供了一种异步回调机制,使我们更新UI 的一套机制,也是一套消息处理 机制

1.2 干什么用

我们可以通过它发送消息,也可以通过它接受消息。

1.3 使用场景

例如: 项目中的无限轮播

2.Handler ,Looper ,MessageQueue 的关系

handler 负责发送消息,Looper 负责接受Handler 发送的消息 ,并直接把消息回传给 Handler 自己,MessageQueue 就是存储消息的容器。

Handler 机制图片

==根据源码 可知,handler 中可以 传入 looper ,而 Looper 可以找到 MessageQueue 对象==

==looper 对象是在 Activity 创建的时候 获取。==

依据上图可知:Handler 首先在主线程(UI 线程)获取对象 mHandler ,mHandler 对象通过 sendMessage() 发送消息,该消息就通过 MessageQueue 的 enqueueMessage() 将 Message 加入队列,该队列是 mHandler 所提供,在主线程中;

而 Looper 可获取 MessageQueue 对象, 通过 prepare(),获取 looper 实例, 该对象 执行 loop() 不断的循环,其为阻塞式方法, 当 looper 对象,获取消息,这执行 消息分发 dispatchMessage() 将消息 发送 到 mHandler 对象的 handlerMessage() 的参数里面,在 handlerMessage() {} 的方法体中 对 msg 进行操作。
形象比喻
加上底层共同理解

3. Handler 中的重要方法

3.1 Messgae

消息理解为 线程间通信的数据单元 。例如 后台线程在处理数据完毕后需要跟新 UI ,则可发送一条包含更新消息的 Message 给 UI 线程。

3.2 MessageQueue

消息队列,用来存放Handler发布的消息,按照先进先出 执行。

3.3 Looper

轮询器,扮演 MessageQueue 和 Handler 之间桥梁的角色,循环取出 MessageQueue 里面的 Message ,并交付 对应的 handler 来处理。

3.4 UI thread

通常就是 main thread ,而 Android 启动程序时 会替他建立 一个 MessageQueue .每一个 线程里面 可含有一个 Looper 对象以及一个MessageQueue 数据结构,在你的应用程序 里,可定义Handler 的子类 来接受 Looper 所送出的消息。

4. handler 的对象

4.1 Handler 封装了消息的发送 (主要包括消息发送给谁) Looper

4.2 Looper 内部包含 一个 MessageQueue ,所以handler 发送的消息 都将到这个队列

4.3 Looper.loop() 方法 ,就是一个 for 死循环,不断地从MessageQueue 取消息,如果有消息就处理消息,没有就阻塞。

4.4 MessageQueue 就是一个消息队列,可以添加消息,处理消息。

4.4 Handler 也不难,比较简单,在构造 Handler 时候内部会跟Looper 进行关联,通过 Looper .myLooper() 获取 Looper ,找到 Looper 也将找到 了 MessageQueue, 在 handler 中发送消息,其实就是 向 MessageQueue 队列中发送消息。

i全局考虑

参考资料

lAndroid 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系

Android中的Handler的机制与用法详解

Android Handler机制

5. 传递Message

由下面源码可知 post 内部 也是 sendMessage()方法

post(Runnable);
 postAtTime(Runnable long);
 postDelayed(Runnable long);
 用于接收子线程发送的数据,并用此数据配合主线程更新UI
   public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }


    private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }

     public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }


     public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

6. 传递Runnable

由源码 可知 sendMessage(..) 方法 最终调用 enqueueMessage() 方法

用于通过 Handler 绑定的消息队列,安排不同操作的执行顺序

sendMessage 类方法,允许你安排一个带数据的 Message 对象到队列中,等待更新。

  • 使用 Handler 在子线程中向 UI 线程发送一个消息进行 UI 的更新
  • 创建一个 Message, Message msg = new Message(); msg.arg1 = 88;
  • handler.sendMessage(msg); msg.obj = xxx; 可以传递一个对象
  • 当然不一定要用 new 一个 Message,也可以复用系统的 message 对象 Message msg = handler.obtainMessage();
用于通过Handler绑定的消息队列,安排不同操作的执行顺序。
1. sendEmptMessage(int);
2. sendMessage(Message);
3. sendMessageAtTime(Message,long);
4. sendMessageDelayed(Message,long);
 public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }
    ---------------------
    此方法内部有直接获取MessageQueue然后调用了enqueueMessage方法
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {  
       msg.target = this;  
       if (mAsynchronous) {  
           msg.setAsynchronous(true);  
       }  
       return queue.enqueueMessage(msg, uptimeMillis);  
   } 

7. 传递 Callback 对象

Callback 用于截获 handler 发送的消息,如果返回 true 就截获成功不会向下传递了。

public Handler mHandler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        // TODO Auto-generated method stub
        Toast.makeText(getApplicationContext(), "HandleMessage 1", Toast.LENGTH_SHORT).show();
        return true;
    }
}) {
    public void handleMessage(Message msg) {
        // TODO Auto-generated method stub
        Toast.makeText(getApplicationContext(), "handleMessage 1", Toast.LENGTH_SHORT).show();
    };
}

上面的示例中,第一个有返回值的 handlerMessage 方法是 Callback 的回调,如果返回true,则不执行下面的 handlerMessage 方法,从而达到拦截 handler 发送的消息的目的,如果返回 false,则会继续执行 handlerMessage 方法。

8. Android 中更新 UI 的几种方式

  • Handler中的post 可以直接更新 UI
  • Handler中的sendMessage 不可以直接更新UI
  • RunOnUiThread 可以直接更新 UI
  • View中的Post 可以直接更新 View UI

猜你喜欢

转载自blog.csdn.net/hyl411136528/article/details/53872280