https://www.jianshu.com/p/b4d745c7ff7a
handler机制源码

1.handler机制的作用
在多线程的场景中,将子线程中需要更新UI的操作信息传递到UI主线程。多个线程并发更新UI的同时 保证线程安全。

Message
线程间通信的数据单元(handler接受和处理的消息对象),存储需要操作的通信信息。

Message Queue
一种数据结构(先进先出)用来存储handler发过来的Message

Handler
主线程与子线程之间通信的媒介,线程消息的主要处理者.1、添加Message到MessageQueue中 2、处理Looper分派过来的Message.

Looper
MessageQueue与Handler之间的媒介,循环的取出MessageQueue里面的Message并分配给相应的Handler去处理。每个线程只能拥有一个Looper,但是一个Looper可以绑定多个线程的Handler
即:多个线程可以向同一个Looper管理的MessageQueue中发送Message。

handler发送消息的方式有2中
handler.sendMessage() 和 handler.post()

handler是怎样绑定线程的
一个handler只能绑定一个Looper对象,一个线程只能绑定一个Looper,但是一个Looper可以有多个handler,一个线程也可以有多个handler。
handler是通过绑定looper来绑定线程。
是通过Handler的构造方法来绑定Looper的

Looper的源码
prepare();
里面会调用prepare(true)方法
    public static void prepare() {
        prepare(true);
    }

    //去创建loopre对象
    private static void prepare(boolean quitAllowed) {
        //判断当前线程的loopre对象是否已经创建过 如果已经创建过就会抛出异常
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        //真正的去创建looper对象,并放进sThreadLocal中
        sThreadLocal.set(new Looper(quitAllowed));
    }
    //Looper的构造方法 创建Looper 和 MessageQueue的对象 和当前线程的引用
    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        //获取当前线程的引用
        mThread = Thread.currentThread();
    }
    //主线程创建Looper的方法并且从sThreadLocal获取这个对象
    public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }
    //从ThreadLocal中获取当前线程的looper对象
    public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }        
    //获取主线程的looper对象
    public static Looper getMainLooper() {
        synchronized (Looper.class) {
            return sMainLooper;
        }
    }
    //获取当前线程的MessageQueue对象    
    public static @NonNull MessageQueue myQueue() {
        return myLooper().mQueue;
    }        
    //当前线程的引用是否是Looper所在的线程    
    public boolean isCurrentThread() {
        return Thread.currentThread() == mThread;
    }        
        
        
    //从开机到现在的毫秒数(手机睡眠的时间不包括在内)    
    final long now = SystemClock.uptimeMillis();    
    //当前消息的前一个消息
    Message prevMsg = null;    
    //当前的消息
    Message msg = mMessages;
    //如果当前的消息不为空并且处理该消息的handler也不为空
    if (msg != null && msg.target == null) {
                    // Stalled by a barrier.  Find the next asynchronous message in the queue.
                    do {
                        prevMsg = msg;
                        msg = msg.next;
                    } while (msg != null && !msg.isAsynchronous());
                }        
        
        
Message的回收和复用:https://www.cnblogs.com/leipDao/p/7850473.html    
//使用的是单链表的数据结构sPool指向链表的头部
private static Message sPool;
public static Message obtain() {
        synchronized (sPoolSync) {
            if (sPool != null) {
                Message m = sPool;
                sPool = m.next;
                m.next = null;
                m.flags = 0; // clear in-use flag
                sPoolSize--;
                return m;
            }
        }
        return new Message();
 }        
obtain()总结

好了,到此主要逻辑就分析完了,obtain()主要逻辑就是先判断缓存池中是否存在空闲message,
如果存在则返回头部message,并且指针指向下一个空闲message,
然后头部的message与之后链表  断开连接。如果不存在空闲message则直接new一个直接返回        
        
        
        
上面的逻辑都是从缓存池中获取的操作,那什么时候向缓存池中存放呢?
public void recycle() {
        if (isInUse()) {
            if (gCheckRecycle) {
                throw new IllegalStateException("This message cannot be recycled because it "
                        + "is still in use.");
            }
            return;
        }
        recycleUnchecked();
}        
void recycleUnchecked() {
        // Mark the message as in use while it remains in the recycled object pool.
        // Clear out all other details.
        flags = FLAG_IN_USE;
        what = 0;
        arg1 = 0;
        arg2 = 0;
        obj = null;
        replyTo = null;
        sendingUid = -1;
        when = 0;
        target = null;
        callback = null;
        data = null;

        synchronized (sPoolSync) {
            if (sPoolSize < MAX_POOL_SIZE) {
                next = sPool;
                sPool = this;
                sPoolSize++;
            }
        }
}

recycle()最主要就是将当前message放入缓存池链表头部。        
        
MessageQueue取出消息的原理: Message next() {}

nextPollTimeoutMillis:阻塞的时间  -1表示会一直阻塞,0表示不阻塞  其他时间为具体阻塞的时间

Handler是怎么发送消息到MessageQueue里面的,又是怎样处理消息的?

1.通过
  private Handler handler=new Handler(){
    @Override
    public void handleMessage(Message msg) {
      super.handleMessage(msg);
    }
  };
    public Handler() {
    //第一个参数==null
        this(null, false);
    }        
        
    public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        //此时这个值是空
        mCallback = callback;
        mAsynchronous = async;
    }
    public void handleMessage(Message msg) {
    }    

    public interface Callback {
        /**
         * @param msg A {@link android.os.Message Message} object
         * @return True if no further handling is desired
         */
        public boolean handleMessage(Message msg);
    }    
        
可以看到在Handler创建的时候会绑定一个当前线程的Looper        
        
在处理消息的时候:
    public void dispatchMessage(Message msg) {
        //如果msg.callback != null 标识是通过 handler.post(new Runnable() {}的方式发送消息的
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            否则就会回调我们的handleMessage方法。
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            否则就会回调我们的handleMessage方法。
            handleMessage(msg);
        }
    }
    handleCallback(msg);    就会执行下面的方法 进而回调我们的Run方法
    private static void handleCallback(Message message) {
        message.callback.run();
    }        
发送消息:
sendEmptyMessage(int what)
  --->sendEmptyMessageDelayed(int what, long delayMillis)
        --->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);
    }
        
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        //最终会跑到MessageQueue中去处理
        return queue.enqueueMessage(msg, uptimeMillis);
    }

handler+looper+messagequeue源码解析的更多相关文章

  1. Android Handler机制(二)---MessageQueue源码解析

    MessageQueue 1.变量 private final boolean mQuitAllowed;//表示MessageQueue是否允许退出 @SuppressWarnings(" ...

  2. Android Handler消息机制源码解析

    好记性不如烂笔头,今天来分析一下Handler的源码实现 Handler机制是Android系统的基础,是多线程之间切换的基础.下面我们分析一下Handler的源码实现. Handler消息机制有4个 ...

  3. Android Handler机制(三)----Looper源码解析

    一.Looper Looper对象,顾名思义,直译过来就是循环的意思,从MessageQueue中不断取出message. Class used to run a message loop for a ...

  4. Android Handler机制(四)---Handler源码解析

    Handler的主要用途有两个:(1).在将来的某个时刻执行消息或一个runnable,(2)把消息发送到消息队列. 主要依靠post(Runnable).postAtTime(Runnable, l ...

  5. Android HandlerThread源码解析

    在上一章Handler源码解析文章中,我们知道App的主线程通过Handler机制完成了一个线程的消息循环.那么我们自己也可以新建一个线程,在线程里面创建一个Looper,完成消息循环,可以做一些定时 ...

  6. Android源码解析——Handler、Looper与MessageQueue

    本文的目的是来分析下 Android 系统中以 Handler.Looper.MessageQueue 组成的异步消息处理机制,通过源码来了解整个消息处理流程的走向以及相关三者之间的关系 需要先了解以 ...

  7. Android -- 从源码解析Handle+Looper+MessageQueue机制

    1,今天和大家一起从底层看看Handle的工作机制是什么样的,那么在引入之前我们先来了解Handle是用来干什么的 handler通俗一点讲就是用来在各个线程之间发送数据的处理对象.在任何线程中,只要 ...

  8. Android -- AsyncTask源码解析

    1,前段时间换工作的时候,关于AsyncTask源码这个点基本上大一点的公司都会问,所以今天就和大家一起来总结总结.本来早就想写这篇文章的,当时写<Android -- 从源码解析Handle+ ...

  9. Android 进阶16:IntentService 使用及源码解析

    It's time to start living the life you've only imagined. 读完本文你将了解: IntentService 简介 IntentService 源码 ...

  10. Handler+Looper+MessageQueue深入详解

    概述:Android中的异步处理机制由四部分组成:Handler+Looper+MessageQueue+message,用于实现线程间的通信. 用到的概念: Handler: 主要作用是发送消息和处 ...

随机推荐

  1. L0范式、L1范式、L2范式解释通俗版

    L0范数是指向量中非0的元素的个数.(L0范数很难优化求解) L1范数是指向量中各个元素绝对值之和 L2范数是指向量各元素的平方和然后求平方根 L1范数可以进行特征选择,即让特征的系数变为0. L2范 ...

  2. 图论之最小生成树问题(kruskal)

    最近有几位同学催我更新,于是来摸摸鱼,来讲一下最小生成树问题. 所谓最小生成树(MST),就是在一张无向带权图中的一棵经过所有节点,边权和最小的一棵树.在实际生活中,可以运用于城镇之间的修路上. 对于 ...

  3. socket.timeout: The read operation timed out完美解决方案【转】

    原博: https://blog.csdn.net/qq_44588905/article/details/113783373 更换 pip 源自国内镜像,在 pip install 后面添加 -i ...

  4. oracle 白名单作用及配置教程

    出于提高数据安全性等目地,我们可能想要对oracle的访问进行限制,允许一些IP连接数据库或拒绝一些IP访问数据库. 当然使用iptables也能达到限制的目地,但是从监听端口变更限制仍可生效.只针对 ...

  5. 《JavaScript高级程序设计》Chapter03 JavaScript语言基础

    目录 Syntax Variable var let const Data Type Undefined Null Boolean Number String Symbol Object Operat ...

  6. LeetCode刷题4:寻找两个正序数组的中位数

    题目: 给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2.请你找出并返回这两个正序数组的 中位数 . 算法的时间复杂度应该为 O(log (m+n)) . 来源:力扣 ...

  7. C# IDataReader转换为Json

    1 /// <summary> 2 /// IDataReader转换为Json 3 /// </summary> 4 /// <param name="dat ...

  8. 【帆吖】Java学习零基础21

    数组 1 package array; 2 3 public class Demo1 { 4 public static void main(String[] args) { 5 int[ ] num ...

  9. 泛型 ? extends E ? super E的区别

    package cn.itcast.generic; import java.util.ArrayList;import java.util.Collection; public class Supp ...

  10. MFC 与 C++ 类型转换

    C++ 中到的类型转换很多,先记录下来,多了写成一个类 1.CString转int 1 CString cNum="9527"; 2 int iNum = 0; 3 iNum=at ...