全面解析Android进阶面试常客之Handler

  • 时间:
  • 浏览:1
  • 来源:决战梭哈棋牌APP下载_决战梭哈棋牌APP官网

ThreadLocal 为处里应用程序应用程序的并发疑疑问供了有五种新的思路。使用你你这种 工具类能够 很简洁地编写出优美的应用程序应用程序。

觉得,他随后有俩个多空最好的法子,具体的代码让大伙儿儿当时人重写你你这种 最好的法子进行处里。代码分析到这里,机会能够 给出下面疑问的答案了。

上面机会嗯将Handler的源码分析了一遍,现在来进行一些总结:

执行到这句代码,说明机会从消息队列中拿到了消息,还记得msg.target吗?随后Message中的target变量呀!也随后发送消息的那个Handler,随后这句代码的本质随后调用了Handler中的dispatchMessage(msg)最好的法子,代码分析到这里是总要很糙小激动了呢!稳住!下面看下dispatchMessage(msg)你你这种 最好的法子,代码如下

Handler在sendMessage总要将当时人设置给Message的target变量即将当时人与发送的消息绑定。

Handler的sendMessage是将Message放入MessageQueue中。

到了这里机会知道Handler的sendMessage是将消息放入MessageQueue中,不难 又是如可从MessageQueue中拿到消息的呢?还会知道答案请继续阅读。

msg.callback随后Runnable对象,当msg.callback不为null总要调用 handleCallback(msg)最好的法子,先来看下 handleCallback(msg)最好的法子,代码如下

如可从MessageQueue中获取Message

总结

Handler的源码分析

机会看一遍上面这段话还是搞不明白ThreadLocal有哪几种用,不难 能够 看下下面代码运行的结果,相信看下结果你就会明白ThreadLocal有哪几种作用了。

觉得,在主应用程序中Android系统机会帮大伙儿儿调用了Looper.prepare最好的法子,能够 看下ActivityThread类中的main最好的法子,代码如下

enqueueMessage最好的法子最后返回的是queue.enqueueMessage(msg, uptimeMillis);也随后调用了MessageQueue中的enqueueMessage最好的法子,下面看下MessageQueue中的enqueueMessage最好的法子,代码如下

由上面的代码能够 看出,Handler的sendMessage最好的法子最后调用了sendMessageAtTime你你这种 最好的法子,觉得,无论时sendMessage、sendEmptyMessage等最好的法子最终总要调用sendMessageAtTime。能够 看一遍sendMessageAtTime你你这种 最好的法子最后返回的是enqueueMessage(queue, msg, uptimeMillis);下面看下你你这种 最好的法子,代码如下

这句话的实质随后调用了Looper的prepare最好的法子,代码如下

要想有以上的收获,就须要研究Handler的源码,从源码中来得到答案。

刚开始探索之路

阅读本文后你机会有以下收获:

使用Handler的sendMessage最好的法子,最后在handleMessage(Message msg)最好的法子中来处里消息。

使用Handler的post最好的法子,最后在Runnable的run最好的法子中来处里,代码如下

再看下Handler的构造最好的法子中的

Handler:负责发送和处里消息。

Message:用来携带须要的数据。

MessageQueue:消息队列,队列上面的内容随后Message。

Looper:消息轮巡器,负责不停的从MessageQueue中取Message。

它们的关系如下图(图片来源于网上)



3、在子应用程序中使用Handler

下面就分析一下Handler的sendMessage最好的法子都做了哪几种,看代码

先从Handler的使用刚开始。大伙儿儿都知道Android的主应用程序能够处里耗时的任务,否者会导致 分析ANR的出现,还会界面的更新又须要要在主应用程序中进行,随后 ,大伙儿儿就须要在子应用程序中处里耗时的任务,还会在主应用程序中更新UI。

Handler的sendMessage最好的法子都做了哪几种

这句代码随后将当前的Handler赋值给了Message中的target变量。随后 ,就将每个调用sendMessage最好的法子的Handler与Message进行了绑定。

本文将Handler的机制删剪讲解了一遍,包括在面试涵盖关Handler的一些疑问,在文章中能够找到答案。

myLooper()最好的法子中代码如下

哪几种是ThreadLocal

本文转载自:www.wizardev.com

学习分享,共勉

文章到了这里大伙儿儿能够 知道以下几点信息了

这句代码。这句代码随后拿到Looper中的mQueue你你这种 成员变量,还会再赋值给Handler中的mQueue,下面看下Looper中的代码

还会,大伙儿儿如可会知道子应用程序中的任务几时完成,又应该哪几种完后 更新UI,又更新哪几种内容呢?为了处里你你这种 疑问,Android为大伙儿儿提供了有俩个多消息机制即Handler。下面看一遍下Handler的常见使用最好的法子,代码如下

由上面的代码不难 看出,post最好的法子最终也是将Runnable封装成消息,还会将消息放入MessageQueue中。下面继续分析dispatchMessage最好的法子中的代码

能够 看一遍在子应用程序中,让应用程序睡了一秒,来模仿耗时的任务,当耗时任务处里完完后 ,Handler会发送有俩个多消息,还会大伙儿儿能够 在Handler的handleMessage最好的法子中得到你你这种 消息,得到消息完后 就能够在handleMessage最好的法子中更新UI了,机会handleMessage是在主应用程序中嘛。到这里就会有以下疑问了:

刚开始语

顺便说下阅读代码应该注意的地方,在分析源码完后 应该知道你分析代码的目的,须要你在为了得到哪几种答案而分析代码;在分析代码时切记要避轻就重,何必 想着要搞定每句代码做了哪几种,要找准大方向。文中的代码已上传到GitHub,能够 在这里获取,与Handler有关的源码在我上传的源码的handler包中。

从这句话中,大伙儿儿能够 知道,在调用Looper.myLooper()完后 须要要先调用Looper.prepare()最好的法子,现在来看下prepare最好的法子中的内容,如下

这里是通过Looper中的myLooper最好的法子来获得Looper实例的,机会Looper为null说说就会抛异常,抛出的异常内容翻译过来随后

看下下面的代码

带着这有俩个多疑问,刚开始分析Handler的源码。

在使用Handler完后 须要要调用Looper.prepare()这句代码,这句代码的作用是将Looper与当前的应用程序进行绑定,在实例化Handler的完后 ,通过Looper.myLooper()获取Looper,还会再获得Looper中的MessageQueue。

好了,现在能够 看看Looper.loop();这句代码到底做了哪几种了loop最好的法子中的代码如下

在介绍它们之间的关系完后 ,先说一下它们每各人的作用。

当使用ThreadLocal 维护变量时,ThreadLocal 为每个使用该变量的应用程序提供独立的变量副本,随后每有俩个应用程序都能够 独立地改变当时人的副本,而不用影响其它应用程序所对应的副本。

上面的代码,我机会进行了次责注释,这里有一句代码非常重要

从上面代码中能够 看一遍,prepare()最好的法子调用了prepare(boolean quitAllowed)最好的法子,prepare(boolean quitAllowed) 最好的法子中则是实例化了有俩个多Looper,还会将Looper设置进sThreadLocal中,到了这里总要必要了解一下ThreadLocalle。

还记得文章刚开始时的有俩个多疑问吗?

先看下在大伙儿儿实例化Handler的完后 ,Handler的构造最好的法子中都做了哪几种事情,看代码

通过源码能够 看一遍Handler的无参构造函数调用了有俩个多参数的构造函数,而在有俩个多参数的构造函数中随后将一些变量进行赋值。

第有五种最好的法子,大伙儿儿机会分析了,下面来分析一下第二种使用最好的法子的原理,先看下Handler的post的最好的法子做了哪几种,代码如下

觉得随后从当前应用程序中的ThreadLocal中取出Looper实例。

现在来一句句的来分析上面的代码,先看下这句

到这里就处里了,为哪几种大伙儿儿在主应用程序中使用Handler完后 不难 调用Looper.prepare最好的法子的疑问了。

题外话,我从事Android开发机会五年了,此前我指导过不少同行。但很少跟大伙儿儿一齐探讨,正好最近我花了有俩个多多月的时间采集出来一份包括全套Android面试精编大全+Android面试视频解析,今天何必 开放给有须要的人,若有关于此方面能够 转发+关注+点赞,点击面试,前往免费领取!



看下这段代码运行完后 打印的log

在文章的前面,贴出了ActivityThread类中的main最好的法子的代码,我不知道细心的你有不难 注意到,在main最好的法子的结尾处调用了一句代码

能够 看一遍其觉得不同的应用程序中对同有俩个多mThreadLocal中的值进行了更改,但最后仍能够 正确拿到当前应用程序中mThreadLocal中的值。由此大伙儿儿能够 得出结论ThreadLocal.set最好的法子设置的值是与当前应用程序进行绑定了的。

在子应用程序中调用Handler的sendMessage最好的法子随后将Message放入MessageQueue中,还会调用Looper.loop()最好的法子来从MessageQueue中取出Message,在取到Message的完后 ,执行 msg.target.dispatchMessage(msg);这句代码,这句代码随后从当前的Message中取出Handler还会执行Handler的handleMessage最好的法子。

这里有一句代码非常重要。

Handler明明是在子应用程序中发的消息如可会会跑到主应用程序中了呢?

Handler的发送消息handleMessage又是如可会接收到的呢?

在子应用程序中Handler在发送消息的完后 机会把当时人与当前的message进行了绑定,在通过Looper.loop()开启轮询message的完后 ,当获得message的完后 会调用 与之绑定的Handler的handleMessage(Message msg)最好的法子,机会Handler是在主应用程序创建的,随后自然就由子应用程序切换到了主应用程序。

这里就又出现了有俩个多疑问:在调用Looper.myLooper最好的法子完后 须要须要机会调用了Looper.prepare最好的法子,即在实例化Handler完后 就要调用Looper.prepare最好的法子,还会大伙儿儿平常在主应用程序中使用Handler的完后 并不难 调用Looper.prepare最好的法子呀!这是如可会回事呢?

2、Handler、Message、MessageQueue以及Looper之间的关系

知道了ThreadLocal.set最好的法子的作用,则Looper.prepare最好的法子随后将Looper与当前应用程序进行绑定(当前应用程序随后调用Looper.prepare最好的法子的应用程序)。

上面的代码随后将消息放入消息队列中,机会消息已成功放入消息队列,则返回true。失败时返回false,而失败的导致 分析通常是机会处里消息队列正在退出。代码分析到这上能够 得出以下两点结论了

上面的代码随后调用了Runnable的run最好的法子。那哪几种情形下if (msg.callback != null)你你这种 条件成立呢!还记得使用Handler的另有五种最好的法子吗?随后调用Handler的post最好的法子呀!这里说明一下,使用Handler觉得是有有五种最好的法子的

让大伙儿儿再回到Handler的构造最好的法子中,看下

上面的代码涵盖一句

无法在未调用Looper.prepare()的应用程序内创建handler

1、Handler的工作原理

同过上面的代码,大伙儿儿能够 知道mQueue随后MessageQueue,在大伙儿儿调用Looper.prepare最好的法子时就将mQueue实例化了。

Handler的使用