如何高效学习Handler?

Android中的Handler类介绍 在Android平台中,新启动的线程是无法访问Activity里的Widget的,当然也不能将运行状态外送出来,这就需要有Handler机制进行消息的传递了,Handler类位于android.os包下,主要的功能是完成Activity的Widget与应用程序中线程之间的交互。接下来对该类中常用的方法进行介绍,如下表所示。方法签名描述Messagemsg)子类对象通过该方法接收信息发送一个只含有what值的消息Messagemsg)发送消息到Handler通过方法接收。 阅读详情

高效学习模型

  • what-->why-->how 模型
  • 是什么?-->为什么使用?-->如何使用?-->实现原理-->总结分享(学以致用)

一.Handler是什么?

  • Handler是Android提供的一种线程间通信的机制

二.为什么使用Handler?

1.UI线程模型(理解):
当启动一个应用时,Android系统会开启一个线程来执行这个应用,该线程即为主线程(Main Thread),
该线程是唯一的,负责处理所有的界面显示及用户操作的响应任务,即负责android.widget和android.view包中所有控件的使用,
由于它负责所有的UI处理工作,故称为UI线程;
如果UI线程中加入了耗时操作,就会阻塞UI线程,给用户带来"死机"的感觉,故耗时操作必须新开线程执行,
但Android规定:非UI线程不能访问UI,故而引入了Hanler来进行线程间通信;
2.该模型中Android做了以下两点规定:
1).不能阻塞UI线程大于5s,否则会报ANR错误;
2).不能让非UI线程访问UI,否则会直接报错;
3.Android是使用大量的消息驱动方式来进行交互的,比如四大组件Activity,Service,Broadcast,ContentProvider的启动过程的交互,都离不开消息机制,
消息机制涉及Handler/Looper/MessageQueue/Message等4个类;
4.UI线程是非线程安全的,为何不设计为线程安全的?
1).UI具有可变性,甚至是高频可变性(如游戏);
2).UI对响应时间的敏感性要求UI操作必须高效;
3).UI组件必须批量来绘制来保证效率;

主线程创建及简要代码说明图:

生产消费模型理解UI线程工作原理图:

三.如何使用Handler?

Handler handler = new Handler(){
@Override
public void handleMessage(final Message msg) {
//这里接受并处理消息
}};
//发送消息
handler.sendMessage(message);
handler.post(runnable);

实例化一个Handler并重写 handleMessage方法, 然后在使用的地方调用它的send以及 post系列方法就可以了, 简单易用,并支持延时消息。

四.实现原理

图解原理:

代码实现原理:

1.创建Handler, 将Handler与Looper关联起来:

  public Handler(Callback callback, boolean async) {
    //检查当前的线程是否有 Looper
    mLooper = Looper.myLooper();
    if (mLooper == null) {
        throw new RuntimeException(
            "Can't create handler inside thread that has not called Looper.prepare()");
    }
    //Looper 持有一个 MessageQueue
   mQueue = mLooper.mQueue;
  }

实现说明:
1).将Handler与Looper关联起来,创建Handler之前一定要先创建Looper,否则会报错;
由于ActivityThread(主线程)在main()方法中已通过Looper.prepareMainLooper()创建了Looper对象,
故能通过Looper.myLooper()获取Looper对象;
2).Looper会持有一个MessageQueue;
3).一个完成的Handler应该如下:

  class LooperThread extends Thread {
    public Handler mHandler;
    public void run() {
    Looper.prepare();
    mHandler = new Handler() {
        public void handleMessage(Message msg) {
            // process incoming messages here
        }
    };
    Looper.loop();
   }
  }

Looper提供了Looper.prepare()方法来创建Looper,
并会借助ThreadLocal来实现与当前线程的绑定功能;
Looper.loop()则会开始不断尝试从MessageQueue中获取 Message,并分发给对应的Handler;
即Handler跟线程的关联是靠 Looper 来实现的。

2.通过send及post系列方法发送Message, 然后将Message添加进入MessageQueue

通过send及post系列方法发送消息,最终会走到 MessageQueue.enqueueMessage(Message,long)方法。
1).Message:
Message是线程间通信的信息载体,包含一些特定的描述和任意的附加数据;
Message具有setData()和getData()方法,它们分别可获取和添加用Bundle对象封装的数据,
这些数据就是线程之间相互传递的数据;
Message对象不建议使用new Message()来获取,可通过Messa.obtain()或Handler的obtainMassage()方法获取;
obtain()可从全局的Message Pool(消息池)中返回一个Message对象;
Message Pool(消息池):是android系统专门用来管理消息的一种机制,
主要是为了避免Message对象频繁的创建销毁带来的开销, 故使用消息池来维护这些对象,
对象使用后可重新放到池中被重新使用,它的大小是10;
2).MessageQueue:
MessageQueue是一个由Message组成的队列,是一个偏底层的类,
它包含的Message由Looper对象分发出去;
Message并不是直接添加进消息队列的, 而是通过与Looper相关的MessageQueue.IdleHandler对象添加;
可使用Looper.myQueue()方法取回当前线程的消息队列;
MessageQueue是通过next()方法获取Message的;

 //MessageQueue
 Message next() {
 //
 for (;;) {
    nativePollOnce(ptr, nextPollTimeoutMillis);
    synchronized (this) {
     //
       Message msg = mMessages;
        //
        if (msg != null) {
            if (now < msg.when) {
                nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
            } else {
                //
                return msg;
            }
        } 
    //
  }
}

图解MessageQueue处理Message:

3.通过Looper.loop()死循环对Message进行获取和分发

Looper:是线程用来运行消息循环的,线程本身无消息循环,
需要调用Looper.prepare()创建Looper对象,然后调用Looper.loop()去处理消息;
Android中系统在启动主线程时会自动为之建立一个Looper对象;
Looper对象通过消息队列来存放消息和事件,一个线程只能有一个Looper,对应一个消息队列;
默认情况下,Handler会与其定义时所在的线程的Looper绑定,如在UI线程中定义,则与UI线程的Looper绑定;

 

//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;
 //...
 for (;;) {
   // 不断从MessageQueue 获取消息
    Message msg = queue.next(); // might block
    //退出Looper 
    if (msg == null) {
        // No message indicates that the message queue is quitting.
        return;
    }
    //...
    try {
        msg.target.dispatchMessage(msg);
        end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();
    } finally {
        //...
    }
    msg.recycleUnchecked();
 }
}
//Handler处理消息
public void dispatchMessage(Message msg) {
 if (msg.callback != null) {
    handleCallback(msg);
 } else {
   if (mCallback != null) {
     if (mCallback.handleMessage(msg)) {
      return;
     }
   }
  //回调到 Handler 的 handleMessage 方法
  handleMessage(msg);
 }
}

简要说明:
1).通过myLooper()获取Looper对象,因Looper持有MessageQueue,进而获取MessageQueue对象;
2).死循环中通过调用queue.next()不断的获取消息;
3).死循环中通过调用msg.target.dispatchMessage(msg)分发消息消息,
msg.target即为发送消息的Handler;
4).dispatchMessage()中调用handleMessage回到UI线程中处理消息;

五.总结分享

核心调用栈流程:
new Handler-->sendMessage()-->enqueueMessage()-->Looper.loop()
-->queue.next()-->msg.target.dispatchMessage()-->handleMessage()

1.创建Handler,通过Looper.myLooper()获取Looper对象,因Looper中持有MessageQueue从而获取到MessageQueue;
2.通过send及post系列方法发送消息, 调用enqueueMessage()将消息添加进MessageQueue;
3.通过Looper.loop()死循环获取和分发消息;
4.通过Hander.handleMessage处理消息;

Handler通信机制详解学习路线

相关的学习笔记可以点击获得Handler通信机制通道

AutoDock Vina 对接计算(大批量) AutoDock Vina是一种用于计算生物分子之间相互作用的计算工具,主要用于蛋白质和小分子(通常是潜在药物分子)之间的对接研究。它可以用于虚拟筛选、药物设计和生物分子结合位点的预测等多个应用领域。 阅读详情

相关推荐

Allegro Design Entry CIS 与 OrCAD Capture CIS:PCB设计工具链中的双雄对决

本文深入对比了Cadence旗下两大原理图设计工具Allegro Design Entry CIS与OrCAD Capture CIS。Allegro Design Entry CIS源自Concept HDL,定位高端,强调自顶向下的层次化设计和与Allegro PCB Editor的无缝约束管理,适合大型复杂系统及团队协作。OrCAD Capture CIS则以其出色的易用性、广泛的兼容性和强大的CIS数据库功能著称,是中小型项目及跨工具链协作的通用选择。文章从历史渊源、核心功能、适用场景等多维度剖析,

bush的博客 489

学习Handler的一些用法

这两天学习到handler机制,初步了解了一些关于它的用法,在这里做一些记录。 1、handler是传送消息的机制,用于在多线程中传送和接收消息。 2、handler用于ui信息的更新。类似于异步更新的效果。 下面是一个handler机制中更换图片的效果。(在布局文件中,只需要建立一个imageView就行了) package com.example.handledemos; imp

u011521890的专栏 501

高温环境下RS485通信故障分析与MOS管解决方案

RS485通信作为工业控制领域的基础总线技术,其可靠性直接影响系统稳定性。在高温等恶劣环境下,传统三极管开关电路会因温度特性导致通信故障。通过分析三极管Ube电压随温度变化的特性,揭示了电路失效的物理原理。相比之下,MOS管作为电压控制型器件,具有温度稳定性好、功耗低等优势,更适合工业环境应用。本文通过一个发动机舱内RS485通信故障的实际案例,详细对比了三极管与MOS管在高温环境下的性能差异,并给出了具体的电路改进方案。该案例对工业通信接口设计具有普遍参考价值,特别适用于需要应对高温、振动等挑战性环境的硬

weixin_42612405的博客 407

如何高效学习Handler?(1),Android架构师必备框架技能核心笔记

这里我特地整理了一份《Android开发核心知识点笔记》,里面就包含了自定义View相关的内容除了这份笔记,还给大家分享Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这几块的内容。非常适合近期有面试和想在技术道路上继续精进的朋友。分享上面这些资源,希望可以帮助到大家提升进阶,如果你觉得还算有用的话,不妨把它们推荐给你的朋友~喜欢本文的话,给我点个小赞、评论区留言或者转发支持一下呗~除了这份笔记,还给大家分享。

qd520_1314的博客 851

java 对接工行聚富通H5聚合支付接口

java 对接工行聚富通H5聚合支付接口

lgl的博客 861

国产麒麟系统中的PaddleOCR离线绿色部署:高效安全的文字识别新纪元

摘要:本文详细介绍了PaddleOCR在银河麒麟V10SP1系统上的离线部署方案。通过Conda虚拟环境隔离依赖,采用离线包安装方式实现无网络部署,支持80+语言识别。重点讲解了模型量化剪枝优化、多线程处理等性能调优技巧,并提供了完整的OCR识别代码示例。该方案具有数据本地化处理的安全优势,适用于医疗票据数字化等对隐私要求严格的场景,同时解决了模型加载失败、内存不足等常见问题。

墨夶的博客 1231

从源码角度分析Handler核心机制

看代码不要什么都看,只需要看主线代码,主线代码逻辑掌握了再选择性的看细节代码。 要知道学什么,该学到什么程度,不然就是什么都会一点,什么都不精。 规划好路线: 1、早点进大厂,评级(需要锻炼技术) 2、创业(需要锻炼技术) 3、转行 一定要确定好边界,不要什么都做,APP开发涉及:Java基础、UI、四大组件、性能优化、NDK、开源框架、架构、数据结构与算法、设计模式等。做APP开发就想办法做好APP开发,不要想着深入研究Linux系统开发,人的精力是有限的,做好一个方向才会精进。 ...

yzpbright的博客 360

Win10环境借助DockerDesktop部署Open web UI集成DeepSeek

Win10环境借助DockerDesktop部署Open web UI集成DeepSeek,并借助DuckDuckGo实现联网查询

虎鲸不是鱼 1705

Android下的Handler

coder是没必要重复造轮子的,写博客亦如此。因为工作忙,学的东西比较多,没法自己来写博客。自己想了个思路就是,把别人的技术精华拿过来,从简到难,慢慢学习。最后提炼,得到自己想学的东西即可,等有时间了可以慢慢消化,进阶。来总结知识点,详细的来写博客。我追求的是总好能一句话来概括知识点,不要长篇大论,最后把大家都绕糊涂了,也没让大家弄懂怎么回事。 1http://blog.youkuaiyun.com...

weixin_30894389的博客 80

【FastDDS】Layer DDS之Subscriber ( 09-Accessing received data)

Fast DDS提供了多种接收数据访问方式:通过读取(read)或提取(take)操作获取数据,其中提取会移除数据而读取保留数据。应用程序可通过序列高效借用接收队列内存,但需及时归还。数据处理时需检查SampleInfo的有效性,可通过监听器回调或等待集机制异步获取数据。等待集允许线程专门等待新数据到达,通过条件触发和超时控制实现可靠的数据接收处理。

Ray Home 863

41、矩形和圆柱形开槽微带贴片天线设计及性能分析

本文提出了一种适用于ISM频段(2.4 - 2.48 GHz)的微带圆形贴片天线,专为生物医学植入和可穿戴设备设计。通过在贴片上蚀刻矩形槽并去除圆柱形槽,实现了小型化与性能优化。采用Rogers 3010基板材料,结合缺陷接地结构(DGS)技术,有效改善了带宽、回波损耗和极化纯度。仿真结果显示,天线在弯曲状态下仍保持良好性能,回波损耗达-13 dB,VSWR为1.6,方向性提升至5.38 dB。与以往设计相比,本次设计在回波损耗和谐振频率稳定性方面表现优异,具备良好的生物相容性和应用潜力。未来将从开槽结构、

github5actions的博客 260

Android面试必备知识点:Android中Handler八大问题汇总

post。

2401_83977357的博客 308

STM32 HAL SDADC DMA

由于项目需要使用STM32F373单片机的SDADC功能对电位计进行检测,网上资料比较少,踩了很多坑,下面进行总结。

weixin_44597885的博客 1198

Android-Handler机制详解

4、Android为什么要设置只能通过Handler机制更新UI?答:最根本的问题是解决多线程并发的问题假设如果一个activity中,有多个线程去更新UI,并且都没有加锁机制,那么会产生什么样的问题?——更新界面混乱;如果对更新UI 的操作都加锁处理的话会产生什么样子的问题?——性能下降对于上述问题的考虑,Android提供了一套更新UI的机制,我们只需要遵循这样的机制就好了。不用关心多线程的问题,更新UI的操作,都是在主线程的消息队列当中轮询处理的。5、handler的原理是什么?

2401_83916435的博客 734

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Android面试题精选:关于-Handler-面试官问了我什么,无经验面试项目助理

它内部靠的是 ThreadLocalMap,线程作为 key,值作为 value,这样我去取对应值的时候,其实通过线程 Key 拿去对应的 value,这样就保证了值是当前线程独享的。答:创建的它的方式有两种,一种是直接 new 一个 Message 对象,另一种是通过调用 Message.obtain() 的方式去复用一个已经被回收的 Message,当然日常使用者是推荐使用后者来拿到一个 Message,因为不断的去创建新对象的话,可能会导致垃圾回收区域中新生代被占满,从而触发 GC。

2401_84104883的博客 984

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

结合源码拆解Handler机制(2),2024年最新字节跳动面试经验

可以看到,此时就是先创建一个prev对象,用来记录当前消息的上一个消息对象的,让它等于p(也就是第三条消息对象),然后p等于p(第三条消息对象)的下一个消息对象(此时是为第二条消息),所以现在p就为第二条消息对象,之后就判断当前对象(第四条消息对象)的时间when是否小于第二条消息对象的when,如果成立,则不用再循环,走msg.next = p;所以,handler的消息排序机制也就是靠这个时间when来决定谁先谁后,小的那个排在大的后面,借由单链表的插入特性来进行插入。

2401_84167046的博客 803

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

2024字节跳动Android开发岗面试,关于Handler,面试官问了我这些……

本文以问答的方式列举了一些在整个面试中,Android岗位被问到的一些关于Handler的问题。(里面还要部分是我在准备面试前在牛客刷到的,还有几个其他的Android朋友被问到的题)由于文章篇幅的原因,很多问题都只是粗略的回答了一些关键的信息,如果有朋友需要更回答的更好,更详细一点的话可以,想要理解的更深一点的话可以来我的GitHub或者**【点这里】免费领取!**

2401_84103844的博客 941

Android面试题精选——再聊Android-Handler机制-2,2024年最新android开发工程师面试题目

在Handler的构造方法中,首先通过Looper.myLooper()方法获取当前线程的Looper对象,如果Looper对象为空,就抛出异常,说当前线程还没有调用Looper.prepare()方法。这道题考察的无非就是你对Handler机制的实现和它的工作原理的了解。)中,当Handler在线程A发送一条消息存放到MessageQueue时,Looper的loop()方法在线程B把消息取出来,并交给Handler处理,所以Handler的处理消息的方法是运行在Looper所在的线程(

2401_84102979的博客 651

Android Handler 从使用到进阶(2),2024年最新2024单招面试是不是变成笔试了

我一直以来都有整理练习大厂面试题的习惯,有随时跳出舒服圈的准备,也许求职者已经很满意现在的工作,薪酬,觉得习惯而且安逸。不过如果公司突然倒闭,或者部门被裁减,还能找到这样或者更好的工作吗?我建议各位,多刷刷面试题,知道最新的技术,每三个月可以去面试一两家公司,因为你已经有不错的工作了,所以可以带着轻松的心态去面试,同时也可以增加面试的经验。我可以将最近整理的一线互联网公司面试真题+解析分享给大家,大概花了三个月的时间整理2246页,帮助大家学习进步。

2401_84102915的博客 819

Android 开发有必要去研究Handler和Binder么?,2024金九银十

以前开始学习Android的时候,有时候想研究源码,研究一些Android底层原理,只能去翻书,或者向其他公司的大牛请教,一个疑问有时候会卡好几天。那时候只要了解,你就能拿到一份薪资丰厚的offer;当时,如果你要是,进阿里腾讯都是很轻松。现在,你只会这些再出去试试?现在面试对Android开发者的要求越来越高了!尤其是阿里、头条、腾讯等大厂,面试问的很多都是原理。

659

Android开发人员必看的 Handler 消息处理机制(源码实战)_android 大量数据handle主线程处理

如果想要成为架构师或想突破20~30K薪资范畴,那就不要局限在编码,业务,要会选型、扩展,提升编程思维。此外,良好的职业规划也很重要,学习的习惯很重要,但是最重要的还是要能持之以恒,任何不能坚持落实的计划都是空谈。如果你没有方向,这里给大家分享一套由阿里高级架构师编写的《Android八大模块进阶笔记》,帮大家将杂乱、零散、碎片化的知识进行体系化的整理,让大家系统而高效地掌握Android开发的各个知识点。

2401_84166147的博客 978

android的消息处理机制(图+源码分析)——Looper,Handler,Message

android的消息处理机制(图+源码分析)——Looper,Handler,Message 作为一个还没毕业的预备程序员,这几天看了有关android消息处理机制学习,I feel android的一大乐趣是可以通过源码学习google大牛们的设计思想。android源码中包含了大量的设计模式,除此以外,android sdk还精心为我们设计了各种helper类,对于和我一样渴

chajinglong的专栏 376

源码解析 Handler 面试宝典,2024年最新字节跳动面试时间

【代码】源码解析 Handler 面试宝典,2024年最新字节跳动面试时间。

2401_83977357的博客 328

Android学习之Handler

Handler机制工作原理 定义 是Android的一套消息传递机制 将工作线程中需更新UI的操作信息 传递到 UI主线程,从而实现 工作线程对UI的更新处理,最终实现异步消息处理 ABOUT 主线程 处理与UI有关的操作 子线程 处理一些耗时的操作(人为手动开启) Message 是线程之前通讯的数据单元,存储需要传递的消息 Handler 添加Message到Message Queue;处理Looper的Message。是线程消息的主要处理者。 Looper 消息循环的核心

colorful的博客 225

mysql handler 详解_Mysql HANDLER语句

HANDLER语法HANDLER tbl_name OPEN [ [AS] alias]HANDLER tbl_name READ index_name { = | <= | >= | < | > } (value1,value2,...)[ WHERE where_condition ] [LIMIT ... ]HANDLER tbl_name READ index_na...

weixin_30641041的博客 695
上一篇: 纵观四十岁的程序员们,他们究竟生活的怎么样?
下一篇: 鸿洋大佬力推,Android面试真相,
懂你的大海
博客等级 码龄6年 9049粉丝 1381原创
评论 11
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值