[转]Handler的运行机制

一. Handler的主要作用

Handler的主要作用:在子线程中发送消息, 在主线程中更新UI。

二. Handler的基本使用

1. Handler.sendMessage(msg)

@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        mTextView.setText(msg.obj + ""); //更新UI
    }
};

//子线程发送消息
new Thread(new Runnable() {
        @Override
        public void run() {
            Message message = new Message();
            message.obj = "6666";
            mHandler.sendMessage(message);
        }).start();

2. Handler.post(msg)

@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler();

//子线程发送消息
new Thread(new Runnable() {
        @Override
        public void run() {
        mHandler.post(new Runnable() { //切换到主线程更新UI
                    @Override
                    public void run() {
                        mTextView.setText("123456");
                    }
                });
        }).start();

三. Handler的运行机制

1. Handler.sendMessage(msg)做了些什么?

Handler.java里面的方法(部分关键代码):
sendMessage()sendMessageDelayed()sendMessageAtTime()enqueueMessage

public final boolean sendMessage(Message msg){
    return sendMessageDelayed(msg, 0);
}

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;
    ...
    return enqueueMessage(queue, msg, uptimeMillis);
}

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this; 
    ...
    return queue.enqueueMessage(msg, uptimeMillis);
}

从上面来看,Handler最终调用了MessageQueue.enqueueMessage()
注意:
msg.target = this;msg.target 表示当前对象Handler, 后面Looper.loop()用到

MessageQueue.enqueueMessage()

boolean enqueueMessage(Message msg, long when) {
{
        ...
        synchronized (this) {
            ...
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            ...
        }
        return true;
    }
}

从代码中慢慢分析,我们可以得出结论:其实MessageQueue.enqueueMessage()方法就是把传进来的Message消息对象,按照时间顺序、队列的结构 保存起来。
在这里,我们并没有看到Handler.handleMessage()方法的执行,继续往下看。

2. 从ActivityThread.main()分析

我们就不慢慢从问题引进来了,直奔主题。

public static void main(String[] args) {
    Looper.prepareMainLooper();  //初始化
    Looper.loop();
}

2.1 Looper.prepareMainLooper()

prepareMainLooper()→prepare()

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对象
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); 

private static void prepare(boolean quitAllowed) {
    //进入ThreadLocal源码里set()和get()可以看出,每个线程只保存一个Looper对象
    //所以每个线程只能调用一次prepare(),否则会抛异常
    if (sThreadLocal.get() != null) {  
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    //ThreadLocal保存Looper对象
    sThreadLocal.set(new Looper(quitAllowed)); 
}

注意:prepare()方法 这里有2个关键点

  1. sThreadLocal.set() 和 get()方法
  2. Looper.java构造方法new Looper().

1.ThreadLocal.java 的set()和get()

public T get() {
    // Optimized for the fast path.
    Thread currentThread = Thread.currentThread();
    Values values = values(currentThread);
    if (values != null) {
        Object[] table = values.table;
        int index = hash & values.mask;
        if (this.reference == table[index]) {
            return (T) table[index + 1];
        }
    } else {
        values = initializeValues(currentThread);
    }

    return (T) values.getAfterMiss(this);
}

public void set(T value) {
     Thread currentThread = Thread.currentThread();
     Values values = values(currentThread);
     if (values == null) {
         values = initializeValues(currentThread);
     }
     values.put(this, value);
 }

set():给当前线程赋值一个:Loop对象
get():获取当前线程的Loop对象

2. Looper.java构造方法

private Looper(boolean quitAllowed) {
    mQueue = new MessageQueue(quitAllowed);
    mThread = Thread.currentThread();
}

主要初始化消息队列MessageQueue,即:一个Loop有一个MessageQueue消息队列对象

总结:Looper.prepareMainLooper() 主要作用:

  1. 初始化Looper.sThreadLocal.set(new Looper(quitAllowed))
  2. 初始化 MessageQueue对象, new Loop() 对应一个MessageQueue对象

2.2 Looper.loop();

下面是部分的关键代码

public static void loop() {
{
        final Looper me = myLooper();
        ...
        final MessageQueue queue = me.mQueue;
        ...
        for (;;) {
            Message msg = queue.next(); // might block
            ...
            msg.target.dispatchMessage(msg);
            ...
            msg.recycle();
        }
    }
}

public static @Nullable Looper myLooper() {
    return sThreadLocal.get();
}

代码里面都有注释,最核心代码是msg.target.dispatchMessage(msg)msg.target就是当前的Handler对象,
接下来我们来看Handler.dispatchMessage()

public void dispatchMessage(Message msg) {
    if (msg.callback != null) {
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

这里就执行了handleMessage()方法

2.3 资源回收处理 msg.recycle()

 private static int sPoolSize = 0;
 private static final int MAX_POOL_SIZE = 50;

public void recycle() {
    clearForRecycle();

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

结论:Msg 对象范围0到50个
最后图解,如下图:
在这里插入图片描述

代码分析基于kk

参考文章:
https://www.jianshu.com/p/969a4e8c1584

猜你喜欢

转载自blog.csdn.net/QWE123ZXCZ/article/details/84875624
今日推荐