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

news2024/11/26 18:46:23

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的发生。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

嵌入式linux系统链接腾讯云的方法

各位开发者大家好,今天主要给大家分享一个,如何使用linux系统链接腾讯云的方法,因为微信小程序越来越普遍,链接腾讯云也是日常必须掌握的一个技能。 第一:【实验目的】 1、linux 系统连接腾讯云的方法 第二:【实验原理】 涉及到原理图添加原理图 2、linux开发板 …

AI 助力问题驱动式学习

文章概括: AI 已经带来学习方式的改变,降低了我们学习知识的难度,加快了我们解决问题的速度。 本文介绍如何通过 AI 工具,通过直接对大模型、对 Agent、对文档、对知识库提问的方式,快速学习知识快速解决问题等。 本…

Vue3学习03 pinia

Vue3学习 pinia pinia一个简单效果搭建 pinia 环境存储读取数据示例 修改数据 (三种方式)storeToRefsgetters$subscribestore组合式写法 pinia 在vue2中使用vuex,在vue3中使用pinia。 集中式状态管理,(状态数据)。多个组件共享数…

vue简单使用二(循环)

目录 属性绑定 if判断&#xff1a; for循环&#xff1a; 属性绑定 代码的形式来说明 三元表达式的写法&#xff1a; if判断&#xff1a; for循环&#xff1a; 完整代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"…

基于web的个人网站的设计与实现(内附设计LW + PPT+ 源码下载)

基于web的个人网站的设计与实现&#xff08;内附设计LW PPT 源码下载&#xff09; 摘 要 随着社会及个人社交应用平台的飞速发展&#xff0c;人们的沟通成本逐渐降低&#xff0c;互联网信息的普及也进一步提升了人们对于信息的需求度&#xff0c;通过建立个人网站的方式来…

【Linux】权限相关命令(九)

文章目录 ls命令&#xff08;常用&#xff09;su命令sudo命令chmod命令chown命令chgrp命令 当谈到Linux系统中的权限时&#xff0c;通常指的是文件和目录的权限。这些权限决定了谁可以对文件或目录进行何种类型的操作。在Linux中&#xff0c;权限通常被分为三个主要方面&#x…

Lesson2: 算法的时间复杂度和空间复杂度

【本节目标】 1. 算法效率 2. 时间复杂度 3. 空间复杂度 4. 常见时间复杂度以及复杂度 oj 练习 1.算法效率 1.1 如何衡量一个算法的好坏 如何衡量一个算法的好坏呢&#xff1f;比如对于以下斐波那契数列&#xff1a; long long Fib(int N) {if(N < 3)return 1;retu…

神经网络模型底层原理与实现8-BERT

首先介绍什么是自监督学习&#xff1a; 普通的有监督学习是每个x对应有个y&#xff0c;x训练得到y&#xff0c;将y与y作比较&#xff0c;而自监督是没有对应y&#xff0c;直接把一部分样本x作为训练目标x&#xff0c;训练得x后和x对比 bert中如何创造x&#xff1a;以文字处理为…

深度学习学习日记4.8(下午)

1.softmax 函数的得出的结果是样本被预测到每个类别的概率&#xff0c;所有类别的概率相加总和等于1。使用 softmax 进行数据归一化&#xff0c;将数字转换成概率。 2.熵&#xff0c;不确定性&#xff0c;越低越好 3.KL 散度交叉熵-信息熵 预测越准&#xff0c;交叉熵越小&am…

QT 信号与槽的简单使用

文章目录 1.通过Singloat and Slots Editor 添加信号与槽2. 通过拖动动态添加3.通过转到槽方式添加&#xff08;自动关联&#xff09;4. 自定义信号与槽&#xff08;connect)4.1 connect方式4.2 自定义信号 1.通过Singloat and Slots Editor 添加信号与槽 点添加&#xff0c;然…

pandas(day10)

一. 各各品类产品交易指数对比 获取文件名 files glob.glob("./*.xlsx")# 读取数据&#xff0c;并改列名&#xff0c;增加一列 品牌 dfs [] for f in files:t f[2:4]df pd.read_excel(f)df["品牌"] tif t "拜耳":df.rename(columns{"…

.NET MVC API Swagger 自动生成API文档入坑

开发环境 Win10 VS2022 .NET8.0 1.从NuGet添加Swagger 在解决方案资源管理器中右键单击项目>管理 NuGet 包 将包源设置为“nuget.org” 确保启用“包括预发行”选项 在搜索框中输入“Swashbuckle.AspNetCore” 从“浏览”选项卡中选择最新的“Swashbuckle.AspNetCore”包&a…

C++ | Leetcode C++题解之第21题合并两个有序链表

题解&#xff1a; 题解&#xff1a; class Solution { public:ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {ListNode* preHead new ListNode(-1);ListNode* prev preHead;while (l1 ! nullptr && l2 ! nullptr) {if (l1->val < l2->val) {prev-…

OJ刷题日记:1、双指针(1)

目录 1、283.移动零 2、1089.复写零 3、202.快乐数 1、283.移动零 题目&#xff1a; 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 …

PC-3000 Portable III、PC-3000 Express、PC-3000 UDMA 有哪些区别?

天津鸿萌科贸发展有限公司从事数据安全业务20余年&#xff0c;在数据恢复、数据取证、数据备份等领域有丰富的案例经验、前沿专业技术及良好的行业口碑。同时&#xff0c;公司面向取证机构及数据恢复公司&#xff0c;提供数据恢复实验室建设方案&#xff0c;包含数据恢复硬件设…

EEPROM读写案例(以AT24C02为例)

本篇文章主要是在学习单片机串行接口时的学习经历&#xff0c;主要侧重于驱动程序的讲解。下文将通过ESP32S3、STM32两款MCU进行编写驱动案例。 1、AT24C02简要说明 AT24C02是美国微芯科技公司生产的电擦写式只读存储器系列中的一款&#xff0c;其容量为2K位&#xff08;即256字…

ios包上架系列 四、虚拟机涉及网站

一、网站相关 苹果开发者平台 https://developer.apple.com/ 谷歌邮箱 https://mail.google.com/mail/u/0/#inbox 微云在线或者安装QQ https://www.weiyun.com/disk 下载下的为zip文件&#xff0c;需要复制里面的内容出来使用 二、环境配置 1、ios-upload 配置&#x…

LeetCode 最长重复子串的更换问题

LeetCode 最长重复子串的更换问题 在处理字符串问题时&#xff0c;我们经常会遇到一些具有挑战性的问题&#xff0c;比如今天的这个问题&#xff1a;给定一个字符串 s 和一个整数 k&#xff0c;我们的任务是找到可以通过最多更换 k 个字符来形成的最长重复子串的长度。 我的解…

【HDFS存储】Java语言实现

Hadoop生态系统中包含多种与其相关联的技术应用&#xff0c;主要包括但不限于HDFS HDFS&#xff08;Hadoop Distributed File System&#xff09;&#xff1a;作为一个高度可靠、高吞吐量的分布式文件系统&#xff0c;它是Hadoop核心技术之一&#xff0c;用于存储海量数据。 J…

如何停止 Win11 自动更新?如何彻底关闭 Windows 更新呢?

如何停止 Win11 自动更新&#xff1f;如何彻底关闭 Windows 更新呢&#xff1f; 段子手168 我们在使用电脑时&#xff0c;有时并不需要 windows 频繁更新系统&#xff0c; 这样可能会使你的 C 盘突然爆满或者系统启动缓慢&#xff0c; 那么如何彻底关闭 Windows 更新呢&#…