Handler源码分析

——————Hnadler实现细节
– 功能
——执行计划任务
——线程间通信
——-确保操作始终在某个特定的线程中执行
– 结论
——1在同一线程可以创建不同的handler
——2handler不能直接创建在没有Looper.prapare这种函数的线程中
——3通过对handler指定Looper才能在不同的线程中运行
——4 一旦message被开始处理,removeMessage是无效的

Handler源码分析_第1张图片
上面是关于handler的原理,其中我们发现,承担线程通信功能其实是looper,通过不断的从消息队列中取出数据,发送个handler,由handlerMessage()来接受消息

对上面的 测试的代码在下面,可以直接下载,也可以自己写demo进行测试

——源码分析
handler的源码实现
Handler()调用了Handler(Callbackcallback,booleanasync)方法,在这个方法中
Handler源码分析_第2张图片
上面是部分的源码,内部创建了Looper对象,如果mLooper不存在的情况下,就爆出了异常
来看看Looper.myLooper的实现
这里写图片描述
调用了线程的get方法

Static final ThreadLocal sThreadLocal=new ThreadLocal();

是一个线程池。存放了Looper,当我们直接去取,当然如果没有内容,就会出错,这也是子线程调用出错的原因,但是在主线程中调用为什么就不会报错,原因是,下面是ActivityThread的源码,也就是activity启动的类,

  public static final void main(String[] args) {
        SamplingProfilerIntegration.start();

        Process.setArgV0("");

        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false);

        Looper.loop();

        if (Process.supportsProcesses()) {
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }

        thread.detach();
        String name = (thread.mInitialApplication != null)
            ? thread.mInitialApplication.getPackageName()
            : "";
        Slog.i(TAG, "Main thread of " + name + " is now exiting");
    }

默认就已经开启了Looper循环,那么我们看看 Looper.prepareMainLooper();和Looper.loop()做了什么
Handler源码分析_第3张图片
下面是最终的调用,向线程中添加个一个loop
Handler源码分析_第4张图片

在创建的Loop时,干了什么?
Handler源码分析_第5张图片
创建了一个消息队列,对,就是用来存放sendMessage消息的队列,所以当我们在子线程中创建时,就需要调用Looper.prepare().当然还有Looper.loop(),去看看干了什么
Handler源码分析_第6张图片
看到这里,仿佛一切都懂了,拿到消息队列,然后通过一个死循环一直重里面去取数据,那么我们回去看看我们重写的sendMessage()的实现
Handler源码分析_第7张图片
里面使用了延迟发送,最终调用了
Handler源码分析_第8张图片
先是取出当前的消息队列,别告诉我mQueue在哪实现的,前面说过了,在loop()里面,
继续前进——————–>>>>>>>
Handler源码分析_第9张图片
先是判断了是否是异步的,queue.enqueneMessage()入队,这里还有注意的的msg.target这个代码,如果当前的里面存放了两个hanler,通过这个target就能知道是发送给哪个handler,这里的this就是当前的handler
那么回到Looper方法里面,我们看看被添加到消息队列里面的消息怎么被拿出来的
Handler源码分析_第10张图片
看出重点来了吗?? Msg.target.dispatchMessage(msg); 这句解释了我上面说的,发送消息被其他handler接收的担忧,那么也就是说真正的消息对列会通过handler.dispatchMessage()将消息取出,那么看看吧,
Handler源码分析_第11张图片
看到这 ,懂了,里面调用了handleMessage()方法,这个方法就是我们实现的那个方法,好吧,handler分析完毕

handler总结
Handler实例与消息处理是关联的,发送和接受需要匹配
只能依附在HandlerThread
可以通过设置Looper来选择Looper来选择器依附的线程
所有的操作都是在用一个线程
removeMessage只能移除队列总的Message

下面是自己写的测试demo以及
部分的系统源代码
demo下载

你可能感兴趣的