android handler源码解析

handler通信是一个内存共享的方案

Handler
public class Handler {
    
    public Handler(@Nullable Callback callback, boolean async) {
        // 拿到Looper里ThreadLocal储存的Looper对象
        mLooper = Looper.myLooper();
    }
    
}

public final class Looper {
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    
     public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }
}

threadlocal中的代码可以看出get()方法会返回一个Looper对象

public class ThreadLocal<T> {
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }
    
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
    
    private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }
    
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
}

上面的代码可以简化为:

public class ThreadLocal<T> {
    public T get() {
        ThreadLocalMap map = t.threadLocals;
        if(map != null) {
            return map.getEntry(this);
        }
         t.threadLocals = new ThreadLocalMap(this, firstValue)
        return null;
    }
}

可以看出handler构造方法里做的事,获取一个当前线程对应的Looper对象,并且这个Looper对象不能为空,否者抛出异常

public class Handler {
    
    public Handler(@Nullable Callback callback, boolean async) {
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread " + Thread.currentThread()
                        + " that has not called Looper.prepare()");
        }
    }
}

因此,在子线程中创建Handler的时候要先构建一个当前线程对应的Looper,即执行Looper.prepare()方法,并且每个线程该方法只能执行一次:

public final class Looper {
    static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
    
    // 静态方法,和sThreadLocal结合就可以看出一个线程只对应一个Looper实例
    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
}

此时注意,Looper中有有一个特殊的prepare方法,就是prepareMainLooper

public final class Looper {
    // 静态方法
   public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();  
        }
    }
}

创建Looper时,构造方法中自动创建一个MessageQueue对象

public final class Looper {
    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
    }
}

2、发送一个Message消息

发送消息最后都会调用这个方法:

    public boolean sendMessageAtTime(@NonNull 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(@NonNull MessageQueue queue, @NonNull Message msg, long uptimeMillis) {
        msg.target = this; // 这边的msg会持有一个handler对象
        return queue.enqueueMessage(msg, uptimeMillis);
    }

这里的message持有一个handler对象,所以使用内部类创建handler的时候有可能会造成内存

持有
内部类会默认持有外部类的引用
msg
handler
activity

继续看源码,sendmessage最后会调用MessageQueue的enqueueMessage方法,这个方法做的事就是往当前线程对应的MessageQueue队列中插入message:

 boolean enqueueMessage(Message msg, long when) {

        synchronized (this) { // 内置锁
           
            msg.when = when;
            Message p = mMessages; // 队列最前面的消息
            boolean needWake;
            if (p == null || when == 0 || when < p.when) { // 判断执行这个消息的时间是否在最前面的消息之前
            
               // 插入到队列最前面
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                
                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;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

MessageQueue是个单链表,优先级队列。

现在,消息已经被发送到消息队列里了,接下来就是消费这个事件。

4、消费事件

loop() 是一个静态方法,调用loop()方法就会开启一个死循环

public final class Looper {
    public static void loop() {
        final Looper me = myLooper();
        final MessageQueue queue = me.mQueue;
    }
}

通过这个死循环把消息回调给handler

public final class Looper {
    public static void loop() {
          for (;;) {
            Message msg = queue.next(); // 取出队列最前面的消息
             if (msg == null) {
                //消息位空的时候才推出循环
                return;
            }
            ...
            // msg.target就是将该消息发送进来的handler,通过这个handler把消息再回调回去
            msg.target.dispatchMessage(msg);
    }
}

最终会调用handleMessage(msg)这个方法,也就是我们平时创建handler的时候重写的这个方法

public class Handler {
     public void dispatchMessage(@NonNull Message msg) {
            ...
            handleMessage(msg); // 最终会回到这个方法,
            ...
    
    }
}

以上就是整个handler工作的基本的流程了。

总结

handler创建的时候同时会获取创建该handler的A线程所对应的looper对象,并调用loop方法不断循环从looper的messagequeue中取出消息,当handler在B线程里面发送消息的时候,会把message加入该handler的looper所对应的唯一messagequeue队列中去,前面说到的loop方法会回调A线程创建的handler的handlemessage方法,由此完成了message从子线程到主线程的切换。

msg
msg
对应一个Looper
对应一个MessageQueue
loop方法
msg
获取最新的消息msg
msg
Handler
sendMessageAtTime
enqueueMessage方法插入队列
Looper
MessageQueue
prepare
不断循环从messagequeue获取消息
handleMessage
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值