该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

1.new Message()与Message.obtain()的区别

前者直接创建新的对象,后者如果有可重复利用的实例会从全局池直接复用,没有的话重新创建实例,可以避免分配新的对象

2.mHandler.sendMessage(Message.obtain()); 与的区别mHandler.sendMessageDelayed(Message.obtain(),1000);

实际上都是调用了 (@NonNull Message msg, long uptimeMillis)方法,

updatime实际上是SystemClock.uptimeMillis() + delayMillis,传递的时间拼加上系统时间,也就是实际执行的时间

3.sendmessageAtTime(@NonNull Message msg, long uptimeMillis)

调用enqueueMessage方法,去将message添加到MessageEnqueue中

4.MessageEnqueue的enqueueMessage方法

MessageEnqueue实际上是一个链表,为什么使用链表?因为插入和删除快

Image

![](img\Image [2].png)

以下是插入链表的方法,

1)如果插入的执行时间小于链表第一个时间,就把当前message设置为第一个,然后当前message的next指向原来的next

2)否则进入一个死循环,一旦找到一个比当前时间大的message,就把message插入到中间,然后跳出循环,如果p.next没有了,就直接插入到最后

![](img\Image [1].png)

5.那是怎么执行的呢?

这里涉及到activity的启动流程,在ActivityThread中有一个man函数,主要代码如下

public static void main(String[] args) {
   
     //省略部分代码
    Looper.prepareMainLooper();

     //省略部分代码
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }

   //省略部分代码
    Looper.loop();


}

Looper.prepareMainLooper() 创建了一个 Looper 对象,而且保证一个线程只有一个 Looper

一旦启动就进入了loop死循环,不断的从 MessageQueue 中去获取message

public static void loop() {
    final Looper me = myLooper();
    if (me == null) {
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;

    //省略部分代码

    for (;;) {
        Message msg = queue.next(); // might block
        if (msg == null) {
            // No message indicates that the message queue is quitting.
            return;
        }

     //省略部分代码
       
        try {
//执行messag
            msg.target.dispatchMessage(msg);
            if (observer != null) {
                observer.messageDispatched(token, msg);
            }
            dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
        } catch (Exception exception) {
            if (observer != null) {
                observer.dispatchingThrewException(token, msg, exception);
            }
            throw exception;
        } finally {
            ThreadLocalWorkSource.restore(origWorkSource);
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }
//省略部分代码
        //释放资源
        msg.recycleUnchecked();
    }
}

手动写一共简单的Handler框架,demo一共有以下类

![](img\Image [3].png)

其中textview的代码为

public class TextView {
    private Thread mThread;
    public TextView() {
        //记录创建时的线程
        this.mThread = Thread.currentThread();
    }
    public void setText(String text) {
        //检测线程是否为建立时的线程
//        checkThread();
        System.out.println(text);
    }
    void checkThread() {
        if (mThread != Thread.currentThread()) {
            throw new RuntimeException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
    }
}

main方法中执行的代码为

        new Thread(() -> {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    //直接在子线程中设置
//                    textView.setText("线程名称->" + Thread.currentThread().getName());
                    //通过hanlder设置
                    Message message = new Message();
                    mHandler.sendMessage(message);
                }).start();

验证结果

1)注释checkThread更新内容,显示线程0

![](img\Image [4].png)

2)取消注释checkThread更新内容,抛异常

![](img\Image [5].png)

3)使用handler发送消息更新内容,结果正常,在主线程主

![](img\Image [6].png)

空文件

简介

Handler原理分析与手写 展开 收起
Android
取消

发行版

暂无发行版

贡献者

全部

近期动态

不能加载更多了
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化