Android 学习随笔 Handler

Handler源码的几个核心类

  Handler、Message、Looper、MessageQueue

Handler发送到收到回调的完整流程

  

 

 Handler

  1:Handler的构造函数

public Handler(@NonNull Looper looper, @Nullable Callback callback, boolean async) {
        mLooper = looper;//持有当前线程的Looper
        mQueue = looper.mQueue;//持有当前线程的Looper内的MessageQueue
        mCallback = callback;//接口回调
        mAsynchronous = async;//是否同步
    }

  2:Handler过时默认函数 空参数构造方法会调用Looper.myLooper()获取当前线程的Looper

  3:Handler会持有当前线程的Looper以及Looper里面的MessageQueue还有回调接口实现对象

Message

  1、Message的构造方法 

1
官方不建议直接使用Message()方式创建Message对象 推荐使用Message.obtain方法创建
1
2
3
4
5
6
7
8
9
10
11
12
13
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();
    }

  

  1.1 关于Message的sPool   Message包含有一个Message属性next 所以Message是一个链表 sPool会进行一个Message对象回收工作  在recycleUnchecked()方法里面进行回收

  1.2 Message的回收创建模式采用享元模式

  1.3 Message的一个一个属性 Handler target 会保存当前发送Message的Handler对象 方便looper取出数据将相应的message发送给对应的Handler的Callback 

MessageQueue

  1 MessageQueue是一个单向链表

  2 MessageQueue内部的next方法内部会调用一个native的方法 nativePollOnce(ptr, nextPollTimeoutMillis);  MessageQueue没有数据就会在这里被阻塞

 

Looper

  1 Looper的构造方法 及为什么一个线程只有一个Looper的原因

1
2
3
4
//私有构造方法 需要调用静态方法prepare()才能创建  类似单例模式<br>private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

 

1
2
3
4
5
6
7
private static void prepare(boolean quitAllowed) {
  //用ThreadLocal来保存当前Looper 和抛异常的方式达到当前线程只有一个Looper的目的
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

  

  2 Looper重要函数loop()  以及loopOnce()   loop内死循环调用loopOnce()方法轮询MessageQueue内的数据  如果MessageQueue没有数据就会被MessageQueue的next()内部阻塞

1
2
3
4
5
6
7
8
9
public static void loop() {
        final Looper me = myLooper();
     ...other//其他代码
        for (;;) {
            if (!loopOnce(me, ident, thresholdOverride)) {
                return;
            }
        }
    }
1
2
3
4
5
6
7
8
9
private static boolean loopOnce(final Looper me,
            final long ident, final int thresholdOverride) {
            ...//other
         
            msg.target.dispatchMessage(msg);
            ...other//
 
        return true;
    }

  

主线程(ActivithThread)中Looper的创建  

  1.ActivityThread的main()方法里面 

1
2
3
4
5
6
7
<em id="__mceDel"><em id="__mceDel">public static void main(String[] args) {<em id="__mceDel">       </em>
     //这里创建主线程的Looper 
        Looper.prepareMainLooper();<br>    //调用Looper.loop()执行死循环
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
</em></em>

  

 

  

posted @   bg_不够  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示