Handler——小白能懂的原理,老鸟需要的面经

1.机制学习

1.1Handler定义

发送并处理 与线程的消息队列关联的Message和Runnable

1.2基本用法

1、Message.obtain() 从消息池取得Message

2、Handler().sendMessage(msg) 发送消息

3、Handler().post  将Runnable包装成Message发送

以下提供一个结构代码

import android.os.Handler;  
import android.os.Message;

public class HandlerTestActivity extends AppCompatActivity {

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case 1:
                    // do something
                    break;
            }
        }
    };
    
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_test);
        
        // message形式
        sendMessage();
        // Runnable形式
        postRunnable();
    }
    
    private void sendMessage() {
        Message msg = Message.obtain();  
        msg.what = 1;  
        mHandler.sendMessage(msg);
    }
    
    private void postRunnable() {
        mHandler.post(new Runnable() {  
            @Override  
            public void run() {  
              // do something
            }  
        });
    }
}

1.3相关类

Message是Handler发送的消息实体

MessageQueue是用来将消息按顺序排队的队列

Looper本质就是一个循环,不停的从MessageQueue中取出消息然后处理

1.4Handler内部运行机制

  • 首先,创建一个Message开始的,交给Handler对象发送,sendMessage和sendMessageDelay最终都是在底层调用了sendMessageAtTime()方法将Message对象放入MessageQueue中的
  • 之后,由Looper的loop()循环从MessageQueue中取出Message对象,调用message.getTarget()获取到发送消息的Handler对象,然后再调用handler.dispatchMessage()方法将信息分发给对应handler执行
  • 最后,Handler在dispatchMessage()方法中判断是否有callback 存在,存在则执行callback的onMessageHandler(),最终交由Message.callback执行否则则执行handler的onMessageHandler()方法。

1.5消息队列MessageQueue存储方式

单链表结构,逻辑上属于线性结构,存储(物理)上属于链式结构

                      头尾元素易于添加和删除

                      随机存储,顺序访问

2.面试问题经验总结

  1. Handler的实现原理: Handler内部通过与Looper和MessageQueue的配合,实现了消息处理和线程间通信的功能。

  2. 子线程中能不能直接new一个Handler,为什么主线程可以: 子线程中不能直接new一个Handler,因为子线程默认没有Looper,而Handler的构造函数中需要传入一个Looper对象。主线程可以是因为主线程默认有与之关联的Looper。

  3. 主线程的Looper第一次调用loop方法,什么时候,哪个类: 主线程的Looper第一次调用loop方法是在ActivityThread类的main方法中。

  4. Handler导致的内存泄露原因及其解决方案: Handler持有外部类的引用可能导致内存泄露,解决方案可以使用弱引用或者在不需要Handler时及时removeCallbacksAndMessages(null)。

  5. 一个线程可以有几个Handler,几个Looper,几个MessageQueue对象: 一个线程可以有多个Handler,但通常只有一个Looper和一个MessageQueue对象。

  6. Message对象创建的方式有哪些 & 区别?Message.obtain()怎么维护消息池的: Message对象的创建方式包括new Message()和Message.obtain(),区别在于Message.obtain()会从消息池中获取Message对象,维护消息池是通过一些静态方法来实现的。

  7. Handler有哪些发送消息的方法: Handler的发送消息的方法包括sendMessage(Message msg)、sendMessageDelayed(Message msg, long delayMillis)、sendMessageAtTime(Message msg, long uptimeMillis)等。

  8. Handler的post与sendMessage的区别和应用场景: post方法是sendMessage方法的封装,post方法会自动将Runnable包装成Message对象发送,适用于不需要传递消息数据的情况。

  9. handler postDealy后消息队列有什么变化,假设先 postDelay 10s, 再postDelay 1s, 怎么处理这2条消息: 先postDelay 10s的消息会在消息队列中排在先,后postDelay 1s的消息会在其后。

  10. MessageQueue是什么数据结构: MessageQueue是一个基于链表的数据结构,用于存储消息队列。

  11. Handler怎么做到的一个线程对应一个Looper,如何保证只有一个MessageQueue: Handler内部通过ThreadLocal来实现一个线程对应一个Looper,并保证只有一个MessageQueue。

  12. ThreadLocal在Handler机制中的作用: ThreadLocal在Handler机制中用于存储每个线程对应的Looper对象。

  13. IdleHandler及其使用场景: IdleHandler是一种回调接口,可以在消息队列空闲时执行特定操作,常用于在UI线程空闲时执行一些耗时操作。

  14. 消息屏障、同步屏障机制: 消息屏障是指通过发送特殊的同步消息来控制消息处理的顺序,同步屏障机制用于保证一组消息按照指定的顺序执行。

  15. 子线程能不能更新UI: 子线程不能直接更新UI,必须通过Handler或者其他线程间通信的方式在主线程中更新UI。

  16. 为什么Android系统不建议子线程访问UI: 因为Android中UI操作必须在主线程中进行,子线程直接操作UI可能导致UI线程安全问题。

  17. Android中为什么主线程不会因为Looper.loop()里的死循环卡死: 主线程中Looper.loop()里的死循环会不断从消息队列中取出消息进行处理,不会导致主线程卡死。

  18. Looper.quit/quitSafely的区别: quit方法会立即终止消息循环,quitSafely会等待消息处理完毕后再退出。

  19. 通过Handler如何实现线程的切换: 可以在Handler的构造函数中传入指定的Looper对象来实现线程的切换。

  20. Handler如何与Looper关联: Handler的构造函数中需要传入一个Looper对象来与之关联。

  21. Looper如何与Thread关联: Looper是通过ThreadLocal来与线程关联的。

  22. Looper.loop()源码: Looper.loop()方法是一个无限循环,不断从消息队列中获取消息并分发处理。

  23. MessageQueue的enqueueMessage()方法如何进行线程同步的: enqueueMessage()方法内部使用了锁来实现线程同步。

  24. MessageQueue的next()方法内部原理: next()方法会阻塞等待消息到来,然后返回消息给Looper进行处理。

  25. 子线程中是否可以用MainLooper去创建Handler,Looper和Handler是否一定处于一个线程: 子线程中不能使用MainLooper创建Handler,Looper和Handler通常是处于同一个线程中。

  26. ANR和Handler的联系: 如果在主线程中有耗时操作没有及时处理,会导致ANR,通过Handler可以将耗时操作放到子线程中执行,避免ANR的发生。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/536526.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用于扩展Qt本身的插件(上)

Qt自身插件 引言示例插件与应用插件的程序作为整体插件和应用插件的程序单独存在实现插件编写测试插件的程序应用插件运行结果引言 用于扩展qt自身的插件按照我的理解分为两种: 1. 直接扩展Qt自身,无需在QtCreator的设计器中加载; 2. 扩展Qt自身,同时需要在QtCreator的设计…

sonar搭建(linux系统)

前景 静态代码扫描是CI/CD中重要的一环,可以在代码提交到代码仓库之后,在CI/CD流程中加入代码扫描步骤,从而及时地对代码进行质量的检查。这可以有效地降低后期维护成本,优化产品质量,提高产品交付速度。同时&#xf…

分类预测 | Matlab实现KPCA-ISSA-LSSVM基于核主成分分析和改进麻雀优化算法优化最小二乘支持向量机分类预测

分类预测 | Matlab实现KPCA-ISSA-LSSVM基于核主成分分析和改进麻雀优化算法优化最小二乘支持向量机分类预测 目录 分类预测 | Matlab实现KPCA-ISSA-LSSVM基于核主成分分析和改进麻雀优化算法优化最小二乘支持向量机分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述…

C语言中的数据结构--链表的应用2(3)

前言 上一节我们学习了链表的应用,那么这一节我们继续加深一下对链表的理解,我们继续通过Leetcode的经典题目来了解一下链表在实际应用中的功能,废话不多说,我们正式进入今天的学习 单链表相关经典算法OJ题4:合并两个…

【分享】各大框架都在使用的Unsafe类

前言 几乎每个使用 Java开发的工具、软件基础设施、高性能开发库都在底层使用了sun.misc.Unsafe,比如Netty、Cassandra、Hadoop、Kafka等。 Unsafe类在提升Java运行效率,增强Java语言底层操作能力方面起了很大的作用。但Unsafe类在sun.misc包下&#x…

大型语言模型有什么用?

大型语言模型有什么用? 大型语言模型识别、总结、翻译、预测、生成文本和其他内容。 AI 应用程序正在总结文章、撰写故事和进行长时间对话——而大型语言模型正在承担繁重的工作。 大型语言模型或 LLM 是一种深度学习算法,可以根据从海量数据集中获得…

linux进阶篇:下载工具wget的安装以及应用

1 wget工具介绍 wget是一个下载文件的工具,它用在命令行下。对于Linux用户是必不可少的工具,我们经常要下载一些软件或从远程服务器恢复备份到本地服务器。 wget支持HTTP,HTTPS和FTP协议,可以使用HTTP代理。所谓的自动下载是指&a…

【C语言基础】:文件操作详解(后篇)

文章目录 一、文件的顺序读写1.1 顺序函数读写函数介绍1.2 fgetc函数和fputc函数1.3 fputs函数和fgets函数1.4 fprintf函数和fscanf函数1.5 fwrite函数和fread函数 二、文件的随机读写2.1 fseek函数2.2 ftell函数2.3 rewind函数 三、文件读取结束的判定3.1 feof函数 四、文件缓…

Linux mmap

目录 内存映射概念: 函数原型: 内存映射步骤: 主要功能 : 系统调用mmap用于共享内存的两种方式: 使用普通文件提供的内存映射: 使用特殊文件提供匿名内存映射: 注意事项 : …

【漏洞复现】潍微科技-水务信息管理平台 ChangePwd SQL注入漏洞

0x01 产品简介 潍微科技-水务信息管理平台主要帮助水务企业实现水质状态监测、管网运行监控、水厂安全保障、用水实时监控以及排放有效监管,确保居民安全稳定用水、环境有效保护,全面提升水务管理效率。 0x02 漏洞概述 潍微科技-水务信息管理平台 ChangePwd 接口存在SQL注…

YOLOv8改进 | 检测头篇 | 自研超分辨率检测头HATHead助力超分辨率检测(混合注意力变换器检测头)

一、本文介绍 本文给大家带来的改进机制是由由我本人利用HAT注意力机制(超分辨率注意力机制)结合V8检测头去掉其中的部分内容形成一种全新的超分辨率检测头。混合注意力变换器(HAT)的设计理念是通过融合通道注意力和自注意力机制…

Windows Edge 兼容性问题修复:提升用户体验的关键步骤

🌟 前言 欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍 &#x…

【随笔】Git 基础篇 -- 远程仓库 git clone(二十五)

💌 所属专栏:【Git】 😀 作  者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大…

FTP所有操作

产生告警原理: 告警中出现 FTP STOP 关键字。Hawkeye keylogger木马名

iPad 无法解锁?修复 iPad 滑动解锁不起作用的 9 个解决方案

“我的 iPad Pro 一整天都工作正常,直到 20 分钟前。当我解锁它时,它不让我向上滑动。屏幕有响应,但我的 iPad 无法解锁。是否有其他人遇到过这种情况并找到了解决方法?解决方案?” ——来自 Apple 支持社区 iPad 屏幕…

前端开发攻略---根据音频节奏实时绘制不断变化的波形图。深入剖析如何通过代码实现音频数据的可视化。

1、演示 2、代码分析 逐行解析 JavaScript 代码块&#xff1a; const audioEle document.querySelector(audio) const cvs document.querySelector(canvas) const ctx cvs.getContext(2d)这几行代码首先获取了 <audio> 和 <canvas> 元素的引用&#xff0c;并使用…

Quartz + SpringBoot 实现分布式定时任务

文章目录 前言一、分布式定时任务解决方案二、Quartz是什么&#xff1f;1.quartz简介2.quartz的优缺点 二、Quartz分布式部署总结 前言 因为应用升级&#xff0c;由之前的单节点微服务应用升级为集群微服务应用&#xff0c;所以之前的定时任务Spring Scheduled不再适用了&…

进程等待waitwaitpid

文章目录 进程等待进程等待的必要性进程等待的方法waitwaitpidstatus 非阻塞等待 进程等待 任何子进程&#xff0c;在退出的情况下&#xff0c;一般必须要被父进程等待 进程等待的必要性 1.父进程通过等待&#xff0c;解决子进程退出的僵尸问题&#xff0c;回收系统资源。 2.…

基于springboot实现知识管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现知识管理系统演示 摘要 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#xff0c;针对这个问题开发一个专门适应师生作业交流形式的网站。本文介绍了知识管理系统的开发全过程。通过分析企业对于知识管理系统的需求&#xff0c;创建了…

012:vue结合纯CSS实现蛇形流程图/步骤条

文章目录 1. 实现效果2. 实现代码 1. 实现效果 2. 实现代码 <template><div class"container"><div v-for"(item, index) in list" class"grid-item"><div class"step">step{{index1}}</div></div&…