Android基础知识巩固系列 Android多线程编程(Handler机制或异步消息处理机制)

Android——Handler详解 1. 简介 Handler是一套 Android 消息传递机制 可以说只要有异步线程与主线程通信的地方就一定会有 Handler。 在多线程的应用场景中,将工作线程中需更新UI的操作信息 传递到 UI主线程,从而实现 工作线程对UI的更新处理,最终实现异步消息的处理 使用Handler消息传递机制主要是为了多个线程并发更新UI的同时,保证线程安全 2. 相关概念解释 Handler、Message、Message Queue、Looper Android消息机制: 以Handler的sendMes 阅读详情

参考网站:https://www.jianshu.com/p/9fe944ee02f7    参考书籍 :《第一行代码》

背景(摘自《第一行代码》):

     和许多其他的GUI库一样,Android的UI也是线程不安全的。也就是说,如果想要更新应用程序里的UI元素,则必须在主线程中进行,否则就会出现异常。                             

一、Handler机制的定义

Handler机制是一套Android消息传递机制,也可以说是异步消息处理机制、Android多线程编程。

二、Handler机制的作用

在多线程的应用场景中,将工作行程中需要更新UI的操作消息传递到UI主线程,从而实现工作线程对UI的更新处理,最终实现异步消息的处理。

三、Handler机制存在的意义(为什么要用Handler消息传递机制?)

简短描述:

     多个线程并发更新UI的同时,保证线程安全。

具体描述:

     背景:在Android开发中,为了UI操作是线程安全的,规定了只允许UI线程(主线程)更新Activity里的UI组件。

     冲突:在实际开发中,存在多个线程并发操作UI组件的情况,导致UI操作的线程不安全。

     诱导出需求为:(1)多个线程可并发操作UI组件(2)保证线程安全

     解决方案:Handler消息传递机制 (工作线程需要更新UI时,通过Handler通知主线程,从而在主线程更新UI操作)

四、Handler机制的相关概念

Android中的异步消息处理主要由4个部分组成:

 Message(消息)、Handler(处理者)、MessageQueue(消息队列)、Looper(循环器)

(以下介绍摘抄《第一行代码》)

1.Message

Message是在线程之间传递的信息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。除了Message的what字段之外,还可以使用arg1和arg2字段来携带一些整型数据,使用obj字段携带一个Object对象。

2.Handler

Handler顾名思义就是处理者的意思,它主要是用于发送和处理消息的。发送消息一般是使用Handlerde的sendMessage()方法,而发出的消息经过一系列地辗转处理后,最终会传递到Handler的handleMessage()方法中。

3.MessageQueue

MessageQueue是消息队列的意思,它主要用于存放所有通过Handler发送的消息。这部分消息会一直存在消息队列中,等待被处理。每个线程中只会有一个MessageQueue对象。

4.Looper 

Looper是每个线程中的MessageQueue的管家(循环器),调用Looper 的loop()方法后,就会进入到一个无限循环当中,然后每当发现MessageQueue中存在一条消息,就会将他取出,并传递到Handler的handleMessage()方法中,每个线程中也只会只有一个Looper 对象。

概念示意图:


 

五、Handler机制使用的方法(方式)

  • Handler使用方式,因发送消息到消息队列的方式不同而不同。
  • 共分为2种:使用Handler.sendMessage()、Handler.post()。

使用步骤:

方式1:使用Handler.sendMessage()

在该使用方式中,又分为2种:新建Handler子类(内部类)、匿名Handler子类。但本质上相同,继承了Handler类&创建子类

第一种,新建Handler子类的方法:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final int UPDATE_TEXT = 1;
    TextView mTextView;
    MyHandler mHandler = new MyHandler();



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.button);
        mTextView = findViewById(R.id.text_view);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message message = new Message();
                        message.what = UPDATE_TEXT;
                        mHandler.sendMessage(message);
                    }
                }).start();
                break;
        }
    }

    class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UPDATE_TEXT:
                    mTextView.setText("你好,世界");
                    break;
            }
        }
    }
}

第二种,匿名Handler子类的方法:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final int UPDATE_TEXT = 1;
    TextView mTextView;
    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UPDATE_TEXT:
                    mTextView.setText("你好,世界");
                    break;
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.button);
        mTextView = findViewById(R.id.text_view);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message message = new Message();
                        message.what = UPDATE_TEXT;
                        mHandler.sendMessage(message);
                    }
                }).start();
                break;
        }
    }

    class MyHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UPDATE_TEXT:
                    mTextView.setText("你好,世界");
                    break;
            }
        }
    }
}

方式2:使用Handler.post()

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    TextView mTextView;
    private Handler mHandler;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.button);
        mTextView = findViewById(R.id.text_view);
        mHandler = new Handler();
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                mTextView.setText("你好,世界!");
                            }
                        });
                    }
                }).start();
                break;
        }
    }
}

六、Handler机制工作原理

  • 理解Handler机制的工作流程,能更好地帮助我们使用Handler和理解其内部流程

6.1 工作流程解析:

  1. 异步通信准备
  2. 消息发送
  3. 消息循环
  4. 消息处理

示意图(注意:这里的处理器其实就是循环器):

 6.2 工作流程图

 6.3 示意图

 

6.4  特别注意

线程(Thread)、循环器(Looper)、处理者(Handler)之间的对应关系如下:

  • 1个线程(Thread)只能绑定1个循环器(Looper),但可以有多个处理者(Handler)
  • 1个循环器(Looper)可绑定多个处理者(Handler)
  • 1个处理者(Handler)只能绑定1个循环器(Looper)

示意图:

七、Handler机制的源码分析

  • 作为程序猿,知其然而必须知其所以然,理解其源码能更好地了解Handler机制的原理。

7.1 Handler机制的核心类

    7.1.1 类说明:

Handler机制中有3个重要的类:

     1.Handler(处理者)

     2.MessaeQueue(消息队列)

     3.Looper(循环器)

    7.1.2 类图:

    7.1.3 具体介绍:

    7.1.4 源码分析:

由于源码的篇幅太长,我这里就直接贴上原网站链接了。

总结图:


八、使用Handler机制的特别注意(内存泄漏:Memory Leak)

  • 在Android开发中,内存泄漏(Memory Leak)十分常见

         1.内存泄漏的定义:本该被回收的对象不能被回收而停留在堆内存中

         2.内存泄漏出现的原因:当一个对象已经不再被使用时,本该被回收但却因为有另外一个正在使用的对象持有它的引用从而导              致它不能被回收。这就导致了内存泄漏(Memory Leak)。

同样篇幅较长,直接贴上原网站链接了。

解决方案有两个:

方案1.静态内部类+弱引用

  • 原理
    静态内部类 不默认持有外部类的引用,从而使得 “未被处理 / 正处理的消息 -> Handler实例 -> 外部类” 的引用关系 的引用关系 不复存在。

  • 具体方案
    将Handler的子类设置成 静态内部类

  • 同时,还可加上使用WeakReference弱引用持有Activity实例
  • 原因:弱引用的对象拥有短暂的生命周期。在垃圾回收器线程扫描时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存
  • 解决代码
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private static final int UPDATE_TEXT = 1;

    static TextView mTextView;
    Handler mHandler;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = findViewById(R.id.button);
        mTextView = findViewById(R.id.text_view);
        mHandler = new MyHandler(this);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Message msg = new Message();
                        msg.what = UPDATE_TEXT;
                        mHandler.sendMessage(msg);
                    }
                }).start();
                break;
        }
    }

    //解决内存泄漏
    private static class MyHandler extends Handler {

        private WeakReference<Activity> mReference;

        MyHandler(Activity activity) {
            mReference = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case UPDATE_TEXT:
                    mTextView.setText("你好,世界");
                    break;
            }
        }
    }

}

方案2.当外部类结束生命周期时,清空Handler内消息队列

  • 原理
    不仅使得 “未被处理 / 正处理的消息 -> Handler实例 -> 外部类” 的引用关系 不复存在,同时 使得 Handler的生命周期(即 消息存在的时期) 与 外部类的生命周期 同步

  • 具体方案
    当 外部类(此处以Activity为例) 结束生命周期时(此时系统会调用onDestroy()),清除 Handler消息队列里的所有消息(调用removeCallbacksAndMessages(null))

  • 具体代码

@Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
        // 外部类Activity生命周期结束时,同时清空消息队列 & 结束Handler生命周期
    }

使用建议:

为了保证Handler中消息队列中的所有消息都能被执行,此处推荐使用解决方案1解决内存泄露问题,即 静态内部类 + 弱引用的方式

 

 

Android异步消息处理之Thread+Handler Android Developers中Keeping Your App Response一文中: No response to an input event (such as key press or screen touch events) within 5 seconds.A BroadcastReceiver hasn't finished executing within 10 se 阅读详情

相关推荐

安卓之异步消息处理机制

安卓异步消息处理机制

eos-i的博客 1175

Android系统Handler详解

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

allen_xu_2012_new的博客 3576

Android进阶系列9-Android异步消息处理Handler机制解析

Android 异步消息处理机制 ,从源码带你理解 Looper、Handler、Message、MessageQueue四者关系,以及使用的一些注意点!

Kerwin的学习历程 686

Android Studio——android中handler用法总结

一、Handler的定义: Handler主要接收子线程发送的数据, 并用此数据配合主线程更新UI,用来跟UI主线程交互用。比如可以用handler发送一个message,然后在handler的线程中来接收、处理该消息,以避免直接在UI主线程中处理事务导致影响UI主线程的其他处理工作,Android提供了Handler作为主线程和子线程的纽带;也可以将handler对象传给其他进程,以便在其他进程...

qq_37746927的博客 4381

先进封装技术 Part03---重布线层(RDL)的科普

RDL是一种在芯片封装过程中用于重新分布电气连接的技术。它通过在芯片表面或中介层上形成额外的布线层,重新分配芯片的I/O(输入/输出)位置,以适应不同的封装需求和提高电气连接的灵活性。

阿拉伯梳子的专栏 4703

Creo报错代码-9?手把手教你重新生成许可证文件(基于Creo 10.0)

本文详细解析Creo报错代码-9的成因及解决方案,重点介绍如何重新生成许可证文件以应对网络环境变化导致的验证失败。通过分步指南和高级技巧,帮助用户有效管理多网络环境下的Creo许可证问题,提升工作效率。

weixin_30839881的博客 560

Android Handler 四个使用实例 及HandlerThread的使用

当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程),主线程为管理界面中的UI控件,进行事件分发,比如说:点击一个Button,Android会分发事件到Button上,来响应你的操作。如果此时需要一个耗时的操作。例如: 联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象,如果5秒钟还没有完成的话,会收到An

二一点 6728

OpenClaw-遇到的问题- FailoverError: Model context window too small (4096 tokens). Minimum is 16000

摘要:OpenClaw配置文件中deepseek-reasoner模型的上下文窗口被默认设置为4096 tokens(实际支持128K),导致系统报错"Model context window too small"。解决方案是删除配置文件中的contextWindow和maxTokens字段,让系统自动获取模型真实能力,并重启OpenClaw服务。配置文件通常位于用户目录下的.openclaw/openclaw.json中。

直到世界的尽头 4163

Handler内存泄露原因及解决方法

三种方案: 1.非静态内部类+弱引用 2.静态内部类+弱引用 3.Activity不可见时,清空消息队列 Android 中handler机制太重要了,无时不刻的都在处理消息队列和任务队列,很多人不注意,在处理延时任务的时候持有activity,导致activity不能被早早的回收,从而降低了APP的效率和性能。 比如下面经典的写法(很多人都会这样写): new Handler().postDelayed(new Runnable() { @Override

u010117864的专栏 870

你的小程序地图功能还只是“摆设”吗?支付宝地图API的深度玩法都在这里了!

🏆本文收录于《滚雪球学支付宝小程序开发》专栏,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

**My Coding Family** 1821

国科大作业考试资料《人工智能原理与算法》2024新编-第二次作业整理

1、对于下列活动,分别给出任务环境的PEAS描述, 并按2.3.2节列出的性质进行分析: 3、为图2.2中描述的吸尘器世界实现一个可以进行性能度量的环境模拟器。你的实现是必须是模块化的,以使传感器、执行器和环境特征(大小、形状、灰尘放置等)便于修改。 4、实现上述题目真空吸尘器环境中的简单反射Agent。用所有可能的初始灰尘分布和Agent位置,运行环境模拟器和Agent。记录Agent在每种情况下的性能评分和总体平均评分。

MatsumotoChrikk 1187

Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38377229 ,本文出自【张鸿洋的博客】很多人面试肯定都被问到过,请问Android中的Looper , Handler , Message有什么关系?本篇博客目的首先为大家从源码角度介绍3者关系,然后给出一个容易记忆的结论。1、 概述Handler 、 Looper 、Mess

Hongyang 24万+

IEC104协议学习专栏内容规划

IEC104协议的编程学习

sixtome 1110

Android Handler 异步消息处理机制的妙用 创建强大的图片加载类

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38476887 ,本文出自【张鸿洋的博客】上一篇博客介绍了Android异步消息处理机制,如果你还不了解,可以看:Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系 。那篇博客的最后,提出可以把异步消息处理机制不仅仅是在MainAc

Hongyang 6万+

基于 SoC 的卷积神经网络车牌识别系统设计(1)引言

通过 CPU 软核 IP 在纯 FPGA 平台上构建一个 AI SoC 卷积神经网络车牌识别系统,其中,缩放、填充层、卷积层、ReLU、池化层、全连接层 IP 都是 Verilog 设计的,同时集成了各种高性能的 IP。这是最具挑战性的 AI SoC 芯片设计项目,集成了 Python 卷积神经网络代码、Verilog 卷积神经网络硬件设计、ARM SoC 设计、ARM 与 FPGA 的交叉编译流程等等。这不仅是科研学习、集创竞赛、秋招求职的一个极具优势的精彩项目,也是目前最火热的芯片行业之中的一个...

新芯设计的博客 3781

VTK 显示大量点云数据及交互(点云拾取、着色、测量等)功能

VTK (Visualization Toolkit) 是一个强大的开源可视化库,非常适合处理点云数据。下面将介绍如何使用 VTK 显示大量点云数据,并实现点云拾取、着色、测量等功能。

深之JohnChen的专栏 1996

Android多线程技术:Handler 异步消息处理机制

当我们在Activity或Fragment内部创建一个匿名内部类的Handler时,这个Handler会隐式持有其外部类的引用(即Activity或Fragment的引用)如果Activity在销毁时,Handler还有未执行完或者正在执行的Message,而Handler又持有Activity的引用,导致GC无法回收Activity,导致内存泄漏。该UI线程处理与UI相关的事件,如:用户的按键事件,把相关的事件分派到对应的组件进行处理等。对于UI线程中比较耗时的工作,开启一个子线程来处理这些工作。

2301_77464642的博客 2310

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Android多线程:Handler runOnUiThread 异步消息处理机制

Android用户界面是与用户交互的接口,对于用户的操作,Android迅速响应用户输入(200ms内)是一个重要目标。因此,一些耗时操作(如:后台下载,异步加载图片等)需要放在子线程中运行,否则会导致主线程阻塞。

IH_LZH的博客 3512

数学建模模型总结

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

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Android 全面解析 Handler 异步消息处理机制

      Android 是不容许在子线程中进行 UI 操作的,但是有些时候我们必须在子线程里去执行一些耗时任务,然后根据执行的结果来更新相应的 UI 控件,对于这种情况,Android 提供了一套异步消息处理机制,完美解决了在子线程中进行 UI 相关操作的问题,今天我们就来一起学习一下这个 Android 系统提供的异步消息处理机制,下面是我们学习的内容大纲                  ...

QDJdeveloper 1348

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Android之handler消息处理机制详解

介绍android中常见的handler消息处理机制,分析源码

qq_43800449的博客 4189

Handler 异步消息处理机制

1.在安卓开发中,我们常常通过一个线程来完成某些操作,然后同步显示对应的视图控件UI上,由于安卓中无法直接通过子线程来进行UI更新操作,因此Android提供了一套异步消息处理机制Handler。 在子线程中更新UI控件会报错: 2. Handler实现方法 /** * Handler: * 1 处理的消息对象就是Message,理解为要传递的消息数据的封装对象 * Message what : 标记,用来区分多个消息 * Message arg1,arg2 : 用来传递int类型的数据

zenmela2011的专栏 1341

Android异步消息处理机制之Handler、Looper、Message

为什么用异步消息处理机制? 因为Android UI线程是线程不安全的,在子线程中更新UI会直接程序崩溃,另外当UI线程需要执行一个比较耗时的操作的话(IO操作,网络通信等),若是执行时间超过5s,程序会直接ANR,为了解决上述问题,可以使用异步消息处理机制Handler,Handler有两大用处: (1) . 在未来的某个时间点执行调度Message或者Runnable对象 (2) . 将执...

小马快跑的博客 1655

Android同步异步任务与多线程和Handler消息处理机制

Android同步异步任务与多线程和Handler消息处理机制

扬帆起航 1483

Handler机制(异步消息处理机制)

Handler机制(异步消息处理机制)

qq_49792179的博客 2049

Handler异步消息处理机制,从源代码看起

在Android开发中经常会遇见异步消息处理的情况,特别是网络请求成功或者失败之后需要更新UI,但是更新UI只能在UI线程里面进行,否则就会报错,这个时候就需要通知UI线程去更新UI,于是Handler出现了。

王三的专栏 3752

安卓Handler消息处理机制详解

消息处理机制可以算得上是每个安卓开发入行最先接触的机制之一。它为我们提供了一种线程间通信方式。本文就讲解Handler提供的各种用法以及其运行机理。

lingchen881218的博客 2315
上一篇: Android基础知识巩固系列 Android之四大组件——ContentProvider(内容提供者)
下一篇: Android基础知识巩固系列 Android之四大组件——BroadcastReceiver(广播)
Peter__Li
博客等级 码龄9年 24粉丝 108原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值