Handler的源码分析
2019独角兽企业重金招聘Python工程师标准>>>
最近复习到了Handler一直只知道怎么用,却没有仔细分析过源码,这下就来看看
为什么要使用handler呢?
因为在安卓应用中ui操作是线程安全的,只能ui线程去操作ui组件,但是在现实开发中,可能有多个线程去并发操作ui,所以将会导致线程不安全,所以就用到了handler
Looper1.主要负责创建message Queue和自身的创建 2. 消息的循环
public static void prepare() {prepare(true); }private static void prepare(boolean quitAllowed) { //判断当前的对象是否为空 ,即prepare不能调用两次if (sThreadLocal.get() != null) {throw new RuntimeException("Only one Looper may be created per thread");}创建looper对象放入线程中sThreadLocal.set(new Looper(quitAllowed)); }
private Looper(boolean quitAllowed) {//looper对象创建了messagequeuemQueue = new MessageQueue(quitAllowed);mThread = Thread.currentThread(); }
2.looper.loop
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;// Make sure the identity of this thread is that of the local process,// and keep track of what that identity token actually is.Binder.clearCallingIdentity();final long ident = Binder.clearCallingIdentity();for (;;) {Message msg = queue.next(); // might blockif (msg == null) {// No message indicates that the message queue is quitting.return;}// This must be in a local variable, in case a UI event sets the loggerfinal Printer logging = me.mLogging;if (logging != null) {logging.println(">>>>> Dispatching to " + msg.target + " " +msg.callback + ": " + msg.what);}final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;final long traceTag = me.mTraceTag;if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {Trace.traceBegin(traceTag, msg.target.getTraceName(msg));}final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();final long end;try { //吧msg交给msg.target实际就是绑定的handler去处理这个方法中调用了handlemessage所以在创建handler 的时候要重写handlemessage方法msg.target.dispatchMessage(msg);end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();} finally {if (traceTag != 0) {Trace.traceEnd(traceTag);}}if (slowDispatchThresholdMs > 0) {final long time = end - start;if (time > slowDispatchThresholdMs) {Slog.w(TAG, "Dispatch took " + time + "ms on "+ Thread.currentThread().getName() + ", h=" +msg.target + " cb=" + msg.callback + " msg=" + msg.what);}}if (logging != null) {logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);}// Make sure that during the course of dispatching the// identity of the thread wasn't corrupted.final long newIdent = Binder.clearCallingIdentity();if (ident != newIdent) {Log.wtf(TAG, "Thread identity changed from 0x"+ Long.toHexString(ident) + " to 0x"+ Long.toHexString(newIdent) + " while dispatching to "+ msg.target.getClass().getName() + " "+ msg.callback + " what=" + msg.what);}msg.recycleUnchecked();} }
Looper的作用就是创建message队列,然后吧队列中的消息派发给handler,然后handler去处理消息
然后我们在去看下Handler的源码
public Handler(Callback callback, boolean async) {if (FIND_POTENTIAL_LEAKS) {final Class<? extends Handler> klass = getClass();if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&(klass.getModifiers() & Modifier.STATIC) == 0) {Log.w(TAG, "The following Handler class should be static or leaks might occur: " +klass.getCanonicalName());}}mLooper = Looper.myLooper();if (mLooper == null) {throw new RuntimeException("Can't create handler inside thread that has not called Looper.prepare()");}mQueue = mLooper.mQueue;mCallback = callback;mAsynchronous = async; }
可以看出handler创建的时候就会绑定他的looper并找见他的队列
handler有两种发送消息的方法 send和post
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;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(MessageQueue queue, Message msg, long uptimeMillis) {msg.target = this;if (mAsynchronous) {msg.setAsynchronous(true);} //看出来最后调用了队列的方法,也就是handler发出的消息,最后会保存到对应的队列中return queue.enqueueMessage(msg, uptimeMillis); }
所以就是一个应用的创建,系统会自动给你生成一个主线程,并在这个主线程中生成一个Looper对象来让你和子线程之间进行消息的传递,Looper会创建一个消息队列,当我们在子线程中给主线程发消息的时候就需要用到handler,handler创建的时候就会去找到这个对应的looper。looper不断的执行loop方法去发消息给队列中 ,没当handler去发送一个消息的时候,就吧消息加入到队列中 ,然后队列的loop方法就会接收到这个消息,然后消息去调用dispatchmsg方法,然后dispatchmsg方法就会调用handler中的handlemessage方法,我们就能接收到这个消息
转载于:https://my.oschina.net/u/3234136/blog/1794086
Handler的源码分析相关推荐
- Handler机制源码分析
一.Handler使用上需要注意的几点 1.1 handler使用不当造成的内存泄漏 public class MainActivity extends AppCompatActivity {priv ...
- Wangle源码分析:编解码Handler
2019独角兽企业重金招聘Python工程师标准>>> 前言 编解码是协议相关的,如果没有编解码Handler,那么在处理网络的粘包.拆包时会变得很复杂.除了http之类的公有协议之 ...
- Wangle源码分析:Pipeline、Handler、Context
2019独角兽企业重金招聘Python工程师标准>>> 基本概念 Wangle中的Pipeline和Netty中的Pipeline是很相似的,既可以将它看为一种职责链模式的实现也可以 ...
- Android多线程:深入分析 Handler机制源码(二)
前言 在Android开发的多线程应用场景中,Handler机制十分常用 接下来,深入分析 Handler机制的源码,希望加深理解 目录 1. Handler 机制简介 定义 一套 Android 消 ...
- Wangle源码分析:Service
2019独角兽企业重金招聘Python工程师标准>>> 前言 Wangle中的Service代表一个远程服务(方法),熟悉RPC的朋友肯定知道这就是一个简单的RPC,当然,和一些常见 ...
- Wangle源码分析:ClientBootstrap
2019独角兽企业重金招聘Python工程师标准>>> ClientBootstrap介绍 ClientBootstrap是wangle作为Client端的一个快速启动辅助类,在经过 ...
- Wangle源码分析:ServerBootstrap
2019独角兽企业重金招聘Python工程师标准>>> ServerBootstrap介绍 ServerBootstrap,顾名思义,它是作为Wangle服务端的一个启动 ...
- Wangle源码分析:EventBaseHandler、AsyncSocketHandler
2019独角兽企业重金招聘Python工程师标准>>> 前言 前面的Wangle源码分析系列文章详细的分析了Pipeline.Handler等实现原理,细心的读者可能发现,每次在构造 ...
- Handler机制的源码分析
2019独角兽企业重金招聘Python工程师标准>>> Handler,MessageQueue,Looper的关系 Looper的作用是在线程中处理消息的 MessageQueue ...
最新文章
- UWP开发入门(十六)——常见的内存泄漏的原因
- oracle数据库实现不同数据库之间的表格数据定期同步
- dell服务器怎么查看网卡型号,dell R730集成网卡什么型号
- 将数组存入mysql数据库,将数组值写入mysql数据库
- 聊聊WebRTC网关服务器1:如何选择服务端端口方案?
- Python中is和==的区别
- Python练习题和答案
- 扫普通二维码打开小程序,可进入体验版
- 计算机中显卡在什么地方 看,电脑显卡在哪个位置
- 皮皮虾如何去水印视频
- 印刷MES管理系统等数字化系统,应用发展如此迅速
- PUE 1.2,总投资达36.4亿,17600个机柜!天和防务拟建陕西最大数据中心
- 6个不为人知的高质量APP推荐:知乎3万人点赞,2万人收藏!
- hadoop 文本统计一个字符的个数_hadoop统计单词个数 - 卡饭网
- 笔记本不能用无线网策略服务器,笔记本不能上网的解决方法适用于使用无线路由器上网...
- latex(2):公式插入
- hust_os_shell算命大师
- Linux——LDAP(相当于Windows下的AD)
- DISPO与EKGRP 的关系(MRP控制者和采购组)
- 机器视觉LED光源照明技术说明
热门文章
- 7-48 字符串输入练习 (I) (15 分)
- 7-8 菲波那契数列 (15 分)
- 7-1 矩阵A乘以B (30 分)
- 基于pyQt的按键响应程序,实现按下按键进行图片曝光(按下按钮,运行另一个曝光图片程序.py)
- MultipartFile和CommonsMultipartFile的区别!
- 模拟ios_王者荣耀策划Donny:安卓IOS今年或实现互通!模拟战一周一更新
- linux硬盘系统安装教程图解,Linux操作系统添加安装新硬盘的方法图解
- 小郡肝火锅点餐系统——项目文档
- 消费者服务消费延时分析
- Egret在Chrome浏览器中的内存占用(内存泄露)