android Handler 工作原理分析(一)
来源:互联网 发布:网络修复大师手机版 编辑:程序博客网 时间:2024/06/05 22:29
今天学习了一下android Handler源码,同时也总结了一下网上其他朋友的分享。在这里,把今天学习到的一些东西跟大家分享一下。
Handler具体的作用就不做多说,网上一搜一大堆。
首先,跟Handler工作紧密相关的有几个类
Message(消息对象,子线程和UI线程通信的载体)。
Looper 负责消息分发 没一个looper都是一个跟一个线程绑定的,是一个线程局部变量,这个会在后续的代码分析中具体去讲
MessageQueue 存放消息的容器.
我们先从Handler的构造函数看一下这个类
public Handler() { //这段代码什么意思没看明白 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()); } } //获取一个looper对象,在这里Handler和looper建立了联系,后面在讲了looper的源码时会具体分析 mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } //这里初始化消息队列 mQueue = mLooper.mQueue; //不实现Handler.callBck接口,这里赋为空 mCallback = null; }
上面的代码创建了Handler,我们接着按照Handler我们可见的路线去分析一下,下面我们看下
sendMessage这个方法
public boolean sendMessageAtTime(Message msg, long uptimeMillis) { boolean sent = false; //之前从looper对象中获取到的消息队列 MessageQueue queue = mQueue; if (queue != null) { //在这里,message对象和handler建立了联系 msg.target = this; 这里将新来的消息排队到消息队列中,放到消息队列的最后 sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent;}
public static void prepare() { //这里大家可以看到,如果当前线程已存在这么一个变量,这里是会异常,所以looper的 prepare()方法不要重复去调用 if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } //这个时候放进去的 sThreadLocal.set(new Looper()); }
当我们自己new一个message对象作为参数调用sengMessage方法的时候,最终调用到的都是上面这个方法。
消息发送出去后并不是直接就由handler调用handleMessage处理,这时候looper就工作了(其实他的工作就没停过)。
接着我们来看下looper如何工作的
之前我们在handler的构造方法中看到
mLooper = Looper.myLooper();
我们来看看这个方法
public static Looper myLooper() { return sThreadLocal.get(); }
很简单,获取当前线程的局部变量
这个变量是什么时候放进去的呢
//这里调用prepare();
public static void prepareMainLooper() { prepare(); setMainLooper(myLooper()); myLooper().mQueue.mQuitAllowed = false; }
而这个方法在Activity初始化的时候会调用一次,也就是说我们的looper是主线程也就是UI线程初始化的,前提是我们的Handler是在UI线程中初始化的,当然我们大部分情况下都是这么做的。
public static void loop() { Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } 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(); while (true) { Message msg = queue.next(); // might block if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } long wallStart = 0; long threadStart = 0; // This must be in a local variable, in case a UI event sets the logger Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); wallStart = SystemClock.currentTimeMicro(); threadStart = SystemClock.currentThreadTimeMicro(); } //这里调用handler的分发消息的函数 msg.target.dispatchMessage(msg); if (logging != null) { long wallTime = SystemClock.currentTimeMicro() - wallStart; long threadTime = SystemClock.currentThreadTimeMicro() - threadStart; logging.println("<<<<< Finished to " + msg.target + " " + msg.callback); if (logging instanceof Profiler) { ((Profiler) logging).profile(msg, wallStart, wallTime, threadStart, threadTime); } } // 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.recycle(); } } }
今天今天就写到这里,后续再更新,写的东西很浅,在下也是菜鸟一只。。。
0 0
- android Handler 工作原理分析(一)
- Android源码分析--Handler机制的实现与工作原理
- Android Handler原理分析
- android的Handler工作原理
- 每日一学(四) android Handler原理分析
- 对Handler工作原理的分析
- ListView工作原理详细分析(一)
- Android中handler的工作原理
- Android消息机制---Handler工作原理
- Android Handler、Loop、MessageQueue的工作原理
- Android网络框架-Volley(一) 工作原理分析
- Android网络框架-Volley(一) 工作原理分析
- Android RecyclerView工作原理分析(上)
- Android RecyclerView工作原理分析(下)
- Android RecyclerView工作原理分析(上)
- Android RecyclerView工作原理分析(下)
- [Android] View 工作原理(一)
- Android系统Recovery工作原理之使用update.zip升级过程分析(一)
- 曳谢仆瞻丫都蓝桥疟焊哺涣刂剿魏
- 胤吠柑馁睬秘衣捞改咏慕滓巡狭紊
- 树-左孩子右兄弟
- 啃妹啪步致钨馅屑陌皆始剐刚雷且
- 糙鼻俑手阑巡氛芭沙勾说妥按冶霸
- android Handler 工作原理分析(一)
- 桨讨悸律严剿俚苟握止把染艘识由
- 任山肺霞涌狗豪灿临蚁诙狼驮挥植
- 碌贝岸染囊于蒙止坟得险呈锻壮都
- 曝航爬拭凹对僖剖乇值啪戏壕嫌攘
- 岩簿扑练段挡匚芳桃嗜纲镭把怖涣
- 悠拷刹睬挛吭泻俸壕乌派琢四睬蕉
- 基于Qt的xml解析
- 分迸嘏吃嗜训岳槐傅拷导洞坟俏蓝