【Android 消息机制】 Handler

Android Handler消息机制详解 Android应用程序是通过消息驱动实现的,因此,Handler机制对于Android应用程序的运行极其重要。 本文详细的介绍了Handler、Looper、MessageQueue、Message、ThreadLocal,内容较长,可以分部分进行学习。文章未详尽之处,欢迎交流,描述有误之处,欢迎指正。 点关注,不迷路;点收藏,你更强;点点赞,我心欢。 阅读详情

一. 概念

Handler是Android消息机制的顶层接口,通过它能够将一个任务切换到Handler所在的线程中去执行,常用于更新UI。
主要包含了Handler,MessageQueue,Looper和ThreadLocal。
为什么要有这种功能?
Android出于安全问题,规定只能在主线程访问UI,并且建议耗时的操作不在主线程中进行。考虑如下情况,我要从服务端拉取很多信息并显示在UI上,这时候就产生了矛盾,因此需要Handler进行线程切换。
在这里插入图片描述

1. ThreadLocal

线程内部的数据存储类,只能在指定线程中获取到存储的数据,其他线程无法获取。在Handler中通过ThreadLocal来获取当前线程的Looper
代码演示:

         val mBooleanThreadLocal : ThreadLocal<Boolean> = ThreadLocal()
         mBooleanThreadLocal.set(true)
         Log.d("Thread",mBooleanThreadLocal.get().toString())
         Thread{
             mBooleanThreadLocal.set(false)
             Log.d("Thread",mBooleanThreadLocal.get().toString())
         }.start()
         Thread{
             Log.d("Thread",mBooleanThreadLocal.get().toString())
         }.start()
         //输出:说明三个线程各自的threadLocal都不一样
         //true
         //false
         //null

2. MessageQueue

即消息队列,底层实现不是队列,而是一个单链表的数据结构
插入方法:enqueMessage
读取方法:next,读取一条消息,并将其移除;如果没有消息,next方法会一直阻塞,直到有消息来

3. Looper

消息循环,即不停地从消息队列中查看是否有新消息,如果有就立刻处理,否则就一直阻塞在那里。
Looper的构造方法,会创建一个MessageQueue

    private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

常用方法:
Looper.loop() 开启消息循环
Looper.prepare() 为当前线程创建一个Looper
prepareMainLooper()为主线程创建Looper
getMainLooper在任何地方都可以获取得到主线程的Looper
quit 直接退出Looper
quitSafely 设定一个退出标记,只有消息队列的已有消息处理完毕后才安全退出

        Thread{
            Looper.prepare()//
            val handler:Handler = Handler()
            Looper.loop()
        }.start()

4. Handler原理

分为消息发送和接收两部分

  • handler将消息发送到Looper的消息队列中(messageQueue),
  • messageQueue 将数据按照时间先后排好队,等待Looper.loop()按照先后顺序取出Message
  • Looper.loop()取出消息之后,调用消息的Message的target,即附属的Handler的dispatchMessage()方法,将该消息回调到handleMessage()方法中
  • handler 在 handleMessage(msg)方法中处理我们自己的逻辑。
    在这里插入图片描述
    数量关系:
    一个Thread只能有一个Looper,可以有多个Handler,而一个Looper中又维护了一个MessageQueue队列

二. 实例演示

1. 整体使用方法

Handler的使用方式有两种:
Handler.sendMessage()

一,创建Handler子类
1、自定义Handler子类,并重写handleMessage()方法
    class mHandler extends Handler {
       //重写handleMessage()方法
         @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //执行的UI操作 
        }
    }
2、主线程中创建mHandler的实例
    private mHandler mhandler = new mHandler();
3、在子线程中创建需要发送的消息对象
    Message msg = Message.obtain();
    msg.what = 1;
4、在子线程中通过Hander发送消息到消息队列
    mhandler .sendMessage(msg);
5、启动子线程
 
二、使用匿名Handler子类
1、在主线程中通过匿名内部类创建Handler类对象
    Handler mhandler =  new Handler(){
        //重写handleMessage()方法
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //执行的UI操作 
        }
    };
2、在子线程中创建需要发送的消息对象
    Message msg = Message.obtain();
    msg.what = 1;
3、在子线程中通过Hander发送消息到消息队列
    mhandler .sendMessage(msg);
4、启动子线程

Handler.post()

1、在主线程中创建Handler实例
    private Handler mhandler = new Handler();
2、在子线程中使用Handler.post()
     mhandler.post(new Runnable() {
                                @Override
                            public void run() {
                                 //执行的UI操作 
                            }
                        });
3、启动子线程

2. 实例演示

  • 耗时子线程的使用
public class MainActivity extends AppCompatActivity {
 
    private static int MSG_1 = 0;
    private Handler handler = new Handler(Looper.myLooper()){
        //运行在主线程
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            if(msg.what == MSG_1){
                textview.setText("Recv Msg:"+(String)msg.obj);
            }
        }
    };
    private Button btn_start;
    private TextView textview;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_start = findViewById(R.id.btn_start);
        textview = findViewById(R.id.textView);
 
        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //模拟耗时任务,在子线程中完成
                new Thread(new Runnable() {
                    @Override
                    public void run() {//子线程任务
                        String buf = "abc123";
                        try {
                            Thread.sleep(6000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //handler send message
                        Message msg = new Message();
                        msg.what = MSG_1;
                        msg.obj = buf;
                        handler.sendMessage(msg);
                    }
                }).start();
                Toast.makeText(MainActivity.this,"main thread go on",Toast.LENGTH_SHORT);
            }
        });
    }
}

文献1
文献2

Android Handler 消息机制 每一个搞 Android 的对 Handler 应该都不陌生,网上大神的文章也是数不尽的。这篇文章是个人在学习 Handler 过程中的一些疑问的记录。 1. 什么是 Handler,有什么作用 Handler 首先是一个 java 类,定义在/frameworks/base/core/java/android/os/Handler.java。但一般提到 Handler 并不专指它自身,常用来代指 Android 中的消息处理机制,或者说线程间通信的工具,典型应用就是在子线程中更新 UI 线程。那么,很显然 阅读详情

相关推荐

安卓中的消息循环机制Handler及Looper详解

我们知道安卓中的UI线程不是线程安全的,我们不能在UI线程中进行耗时操作,通常我们的做法是开启一个子线程在子线程中处理耗时操作,但是安卓规定不允许在子线程中进行UI的更新操作,通常我们会通过Handler机制来完成该功能,即当子线程中耗时操作完成后,在子线程中通过Handler向主线程发送消息,在主线程中的Handler的handleMessage方法中处理接受到的消息。这就是安卓中的消息机制,安

(* ̄︶ ̄) 7960

Android——Handler一篇就看懂

Android handler的详细讲解

未来源起的博客 9698

深入分析Android Handler消息机制

概述 Handler是Android消息机制的上层接口。通过它可以轻松地将一个任务切换到Handler所在的线程中去执行。通常情况下,Handler的使用场景就是 更新UI。 Handler的使用 在子线程中,进行耗时操作,执行完操作后,发送消息,通知主线程更新UI。 public class Activity extends android.app.Activity { private Handler mHandler = new Handler(){ @Override

nufuli123的博客 1586

Android子线程如何创建Handler

了解Handler原理的都知道,Handler的消息处理是通过Looper.loop()里的死循环,不断的从消息队列中取出消息并处理,在主线程中已经自动调用了Looper.loop()方法,所以我们可以直接使用new Handler()创建,而在子线程中需要我们手动创建。所以必须要保证run()执行完,再去执行getLooper()方法,可以使用wait()和notify()实现。我们平时使用Handler都是在主线程中new Handler(),那么在子线程中也可以这样创建Handler吗?

小旭的专栏 1149

架构决策之消息中间件MQ系列六-Pulsar

一、架构

恰恰虎的博客 7253

单细胞转录组聚类分析R包——SC3的应用

前言 在做单细胞相关聚类分析的过程中,为了研究异质性,发现了一种专门用于单细胞转录组的聚类分析R包——SC3(single cell consensus clustering,单细胞一致性聚类)。该聚类算法发表于Nature Methods(2017),能够让单细胞RNA-seq基于转录组特征对细胞类型进行定量表征。这是一种用户友好的无监督聚类工具,它通过一致方法将多个聚类解决方案组合在一起,从而得到高精度和鲁棒性的分群结果。SC3包的官方具体使用教程见:http://www.bioconductor.or

m0_51042606的博客 5005

带你深入了解Android Handler的用法

在 Android 开发中,使用多线程是非常常见的,但是在 Android 中,有一个 UI 线程,也就是主线程,所有的UI操作必须在主线程中完成,否则就会抛出 CalledFromWrongThreadException 异常,这个异常的原因是 Android 不允许在子线程中直接访问 UI 控件。而 Handler 的主要作用就是用于子线程与主线程之间进行通讯,在应用程序内传递消息、更新 UI 等各种场景下,都可以使用 Handler 来实现。

Dakaring的专栏 6227

Android车载多屏开发实战:从零搭建同显/异显Demo(附源码)

本文详细介绍了Android车载多屏开发的实战经验,从零搭建同显/异显Demo,涵盖多屏模拟、核心API调用、同显/异显架构实现及性能优化等关键环节。通过C++构建完整开发链路,帮助开发者快速掌握多屏同显和多屏异显技术,提升智能座舱系统的交互体验。附源码供参考。

weixin_29233857的博客 403

Android系统Handler详解

Handler是一套 Android 消息传递机制,主要用于线程间通信。用最简单的话描述: handler其实就是主线程在起了一个子线程,子线程运行并生成Message,Looper获取message并传递给Handler,Handler逐个获取子线程中的Message.Binder/Socket用于进程间通信,而Handler消息机制用于同进程的线程间通信可以说只要有异步线程与主线程通信的地方就一定会有 Handler。

allen_xu_2012_new的博客 3576

FlashAttention 快速安装指南(避免长时间编译)

FlashAttention 编译太慢?本篇提供无需编译的预编译 wheel 快速安装方案,适配多版本 Python、PyTorch 和 CUDA,极大节省部署时间!

Junseer的博客 9718

从 ST22 到根因定位:ABAP Dumps 全景排查指南(含典型 Dump 案例、修复套路与云时代实践)

本文系统介绍了SAP系统中ABAP短转储(Dump)的分析方法。首先指出短转储是程序运行时无法处理的错误导致系统强制终止执行。文章详细解析了短转储报告各区块的作用:从概述性的Short Text和What happened,到核心的Error Analysis和Source Code Extract,再到关键的系统字段Contents of system fields和调用栈Active Calls/Events。针对不同场景提供了排查建议:客户代码应建立可控边界,标准对象优先查阅SAP Notes。最后推

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 484

Android基础之Handler分析,vivo安卓开发面试

这个锁,说明的是对所有调用同一个MessageQueue对象的线程来说,他们都是互斥的,然而在我们的Handler里 面,一个线程是对应着一个唯一的Looper对象,而Looper中又只有一个唯一的MessageQueue(这个在上文中也有介绍)。Handler是用于线程间通信的,但是它产生的根本并不只是用于UI处理,而更多的是handler是整个app通信的框架, 大家可以在ActivityThread里面感受到,整个App都是用它来进行线程间的协调。如果频繁的生成对象就会产生内存抖动,也会引发OOM。

m0_57502067的博客 1005

YOLOv11涨点改进 | Neck改进篇 | YOLOv11引入 BiFPN双向特征金字塔网络,显著提升了多尺度特征融合效率

本文介绍了基于BiFPN特征融合模块优化的YOLOv11目标检测模型。BiFPN通过双向跨尺度连接和加权特征融合机制,显著提升了多尺度特征融合效率。该方法在COCO数据集上实现了55.1AP的检测精度,同时大幅降低计算成本(减少13-42倍FLOPs)。文章详细解析了BiFPN模块结构、核心代码实现方法,并提供了YOLOv11-BiFPN配置文件的修改指导,为计算机视觉领域提供了一种高效的目标检测解决方案。

Ai缝合怪、助力小伙伴高效发论文 712

【Android】Handler消息机制

Android消息机制学习分享

m0_74448051的博客 1649

PCIE的MSI中断处理机制与优化策略

PCIe设备的。

xiaoheshang_123的博客 516

华为OD面试手撕真题目录

2026最新华为OD面试手撕真题 , 提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解.

qq_45776114的博客 1万+

【安卓学习笔记】Android Handler 消息机制探究

一、概述 1.android消息机制的含义: Android消息机制,其实指的就是 Handler 的运行机制 而 Handler 要正常运作,又需要底层的 MessageQueue , Looper , ThreadLocal 共同配合 因此所谓的消息机制,其实主要讲的就是 Handler ,MessageQueue ,Looper ,ThreadLocal 四者的关系 2.概述Handler工作流程: 首先是构造 Handler ,这时候会通过 ThreadLocal 找到当前线程的 Looper

tulensa的博客 1499

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

【Android 消息机制】Handler

Android专题学习-Handler总结

studyForMokey的博客 983

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Android Handler消息处理机制

消息处理机制本质:一个线程开启循环模式持续监听并依次处理其他线程给它发的消息。简单的说:一个线程开启一个无限循环模式,不断遍历自己的消息列表,如果有消息就挨个拿出来做处理,如果列表没消息,自己就堵塞(相当于wait,让出cpu资源给其他线程),其他线程如果想让该线程做什么事,就往该线程的消息队列插入消息,该线程会不断从队列里拿出消息做处理。

轻口味的专栏 3402

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

深入解析Android中Handler消息机制

通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作为map的key来使用的。首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。

老皮的博客 266

Android Handler 消息循环机制

核心思想:利用 Linux 的epoll机制,在无事可做时让线程进入休眠,在有新消息时能及时唤醒,从而兼顾了响应效率和资源消耗。

w2064004678的博客 1386

Android的消息机制--Handler

Android handler原理解析

weixin_42277946的博客 2972

Android 基于Handler 剖析消息机制

Android handler 处理消息机制是Android 系统、应用开发中一个十分重要的利器,可以简单、轻松的将事情异步分解处理。Handler 与Looper、MessageQueue、Message类紧密结合,实现了完整的消息机制。

私房菜 3823

android Handler Looper,MessageQueue消息机制原理

安卓消息处理类: Looper、Handler、MessageQueue、Message、ThreadLocal、ThreadLocal.Values、HandlerThread。 Looper: 线程默认是没有消息循环的,要为一个线程创建一个消息循环通过调用prepare(),然后在调用loop()方法进入消息循环(这意味着线程将一直在此方法循环)。例如: class LooperThr

ZhouLi_优快云的专栏 9992

安卓消息机制之Handler基础知识

相信大家从网上也看到过Handler的代码解析,下面我将从我个人理解的角度,以尽量通俗易懂的语言带领大家对Handler的用法以及源码设计进行解读。

weixin_39330114的博客 1452

Android全面解析之由浅及深Handler消息机制

前言 很高兴遇见你~ 欢迎阅读我的文章。 关于Handler的博客可谓是俯拾皆是,而这也是一个老生常谈的话题,可见的他非常基础,也非常重要。但很多的博客,却很少有从入门开始介绍,这在我一开始学习的时候就直接给我讲Looper讲阻塞,非常难以理解。同时,也很少有系统地讲解关于Handler的一切,知识比较零散。我希望写一篇从入门到深入,系统地全面地讲解Handler的文章,帮助大家认识Handler。 这篇文章的讲解深度循序渐进,不同程序的读者可选择对应的部分查看: 第一部分是对于Handler的入门概述。

一只修仙的猿 1万+
上一篇: [Kotlin入门] 单例、数据类、静态
下一篇: [Android基础] 学习记录2
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值