android之Handler的使用,回到主线程更新UI的四种方法

2024-05-31 09:48

本文主要是介绍android之Handler的使用,回到主线程更新UI的四种方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Android为了线程安全,并不允许我们在UI线程外操作UI;很多时候我们做界面刷新都需要通过Handler来通知UI组件更新!除了用Handler完成界面更新外,还可以使用runOnUiThread()来更新,甚至更高级的事务总线。 

当我们的子线程想修改Activity中的UI组件时,我们可以新建一个Handler对象,通过这个对象向主线程发送信息;而我们发送的信息会先到主线程的MessageQueue进行等待,由Looper按先入先出顺序取出,再根据message对象的what属性分发给对应的Handler进行处理。

Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。

  • UI线程:就是我们的主线程,系统在创建UI线程的时候会初始化一个Looper对象,同时也会创建一个与其关联的MessageQueue;
  • Handler:作用就是发送与处理信息,如果希望Handler正常工作,在当前线程中要有一个Looper对象
  • Message:Handler接收与处理的消息对象
  • MessageQueue:消息队列,先进先出管理Message,在初始化Looper对象时会创建一个与之关联的MessageQueue;
  • Looper:每个线程只能够有一个Looper,管理MessageQueue,不断地从中取出Message分发给对应的Handler处理!

Handler在子线程中:

如果是Handler写在了子线程中的话,我们就需要自己创建一个Looper对象了!创建的流程如下:

1 )直接调用Looper.prepare()方法即可为当前线程创建Looper对象,而它的构造器会创建配套的MessageQueue; 

2 )创建Handler对象,重写handleMessage( )方法就可以处理来自于其他线程的信息了! 3 )调用Looper.loop()方法启动Looper

 new Thread(new Runnable() {@Overridepublic void run() {/** handler使用步骤*gei threadLocal设置了一个looper对象* 在looper的构造方法中,创建了一个messageQueue对象* */Looper.prepare();/*在构造方法中获取looper和looper中的messageQueue** */Handler handler=new Handler(){@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);}};/*奖message发送到messagequeue中,在messageQueue里面,所有的message都是时间为顺序从小到大排列** */
handler.sendEmptyMessage(0);
/*
*顺序取出messageQueue中的message
*并且执行message。target。dispatchMessage();其中的message。target就是发送这个消息的handler
* 每一条消息都有一定的执行时间,handler会判断时间有没有到,如果没到时间会等待,
* */
Looper.loop();}}).start();

 

----------handler的使用------

通过Message与Handler进行通信的步骤是: 
1. 重写Handler的handleMessage方法,根据Message的what值进行不同的处理操作 
2. 创建Message对象 
虽然Message的构造函数式public的,我们还可以通过Message.obtain()或Handler.obtainMessage()来获得一个Message对象(Handler.obtainMessage()内部其实调用了Message.obtain())。 
3. 设置Message的what值 
Message.what是我们自定义的一个Message的识别码,以便于在Handler的handleMessage方法中根据what识别出不同的Message,以便我们做出不同的处理操作。 
4. 设置Message的所携带的数据,简单数据可以通过两个int类型的field arg1和arg2来赋值,并可以在handleMessage中读取。 
5. 如果Message需要携带复杂的数据,那么可以设置Message的obj字段,obj是Object类型,可以赋予任意类型的数据。或者可以通过调用Message的setData方法赋值Bundle类型的数据,可以通过getData方法获取该Bundle数据。 
6. 我们通过Handler.sendMessage(Message)方法将Message传入Handler中让其在handleMessage中对其进行处理。 

需要说明的是,如果在handleMessage中 不需要判断Message类型,那么就无须设置Message的what值;而且让Message携带数据也不是必须的,只有在需要的时候才需要让其携带数据;如果确实需要让Message携带数据,应该尽量使用arg1或arg2或两者,能用arg1和arg2解决的话就不要用obj,因为用arg1和arg2更高效。

 

Handler handler = new Handler()
{public void handleMessage(android.os.Message msg) {switch (msg.what){case 1:String str= (String) msg.obj;reponsedattx.setText(str);break;}};
};

 

 

 

//get同步请求---http://ddb.cn/api/VlianbaoCash/depositpublic void gettongbuDatasync(){new Thread(new Runnable() {@Overridepublic void run() {OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象Request request = new Request.Builder().url(String.valueOf(test.getText()))//请求接口。如果需要传参拼接到接口后面。.build();//创建Request 对象Response    response=null;try {response = client.newCall(request).execute();//得到Response 对象Log.e("kwwl","get同步res=="+response.body().string());String resstr=response.body().string();Message msg=new Message();//虽然Message的构造函数式public的,我们也可以通过以下两种方式通过循环对象获取Message//msg = Message.obtain(uiHandler);//msg = uiHandler.obtainMessage();//what是我们自定义的一个Message的识别码,以便于在Handler的handleMessage方法中根据what识别//出不同的Message,以便我们做出不同的处理操作msg.what = 1;//我们可以通过arg1和arg2给Message传入简单的数据msg.arg2 = 321;msg.obj="jjjj";//我们也可以通过给obj赋值Object类型传递向Message传入任意数据//msg.obj = null;//我们还可以通过setData方法和getData方法向Message中写入和读取Bundle类型的数据//msg.setData(null);//Bundle data = msg.getData();//将该Message发送给对应的Handler*****handler.sendMessage(msg);} catch (IOException e) {e.printStackTrace();}}}).start();}

 

 

 

-------回到主线程更新UI的四种方法,参考:https://blog.csdn.net/mislaydu/article/details/51776247

 

 

 

这篇关于android之Handler的使用,回到主线程更新UI的四种方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1017704

相关文章

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

关于集合与数组转换实现方法

《关于集合与数组转换实现方法》:本文主要介绍关于集合与数组转换实现方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、Arrays.asList()1.1、方法作用1.2、内部实现1.3、修改元素的影响1.4、注意事项2、list.toArray()2.1、方

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

一文详解Git中分支本地和远程删除的方法

《一文详解Git中分支本地和远程删除的方法》在使用Git进行版本控制的过程中,我们会创建多个分支来进行不同功能的开发,这就容易涉及到如何正确地删除本地分支和远程分支,下面我们就来看看相关的实现方法吧... 目录技术背景实现步骤删除本地分支删除远程www.chinasem.cn分支同步删除信息到其他机器示例步骤

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

ModelMapper基本使用和常见场景示例详解

《ModelMapper基本使用和常见场景示例详解》ModelMapper是Java对象映射库,支持自动映射、自定义规则、集合转换及高级配置(如匹配策略、转换器),可集成SpringBoot,减少样板... 目录1. 添加依赖2. 基本用法示例:简单对象映射3. 自定义映射规则4. 集合映射5. 高级配置匹

Spring 框架之Springfox使用详解

《Spring框架之Springfox使用详解》Springfox是Spring框架的API文档工具,集成Swagger规范,自动生成文档并支持多语言/版本,模块化设计便于扩展,但存在版本兼容性、性... 目录核心功能工作原理模块化设计使用示例注意事项优缺点优点缺点总结适用场景建议总结Springfox 是

嵌入式数据库SQLite 3配置使用讲解

《嵌入式数据库SQLite3配置使用讲解》本文强调嵌入式项目中SQLite3数据库的重要性,因其零配置、轻量级、跨平台及事务处理特性,可保障数据溯源与责任明确,详细讲解安装配置、基础语法及SQLit... 目录0、惨痛教训1、SQLite3环境配置(1)、下载安装SQLite库(2)、解压下载的文件(3)、

使用Python绘制3D堆叠条形图全解析

《使用Python绘制3D堆叠条形图全解析》在数据可视化的工具箱里,3D图表总能带来眼前一亮的效果,本文就来和大家聊聊如何使用Python实现绘制3D堆叠条形图,感兴趣的小伙伴可以了解下... 目录为什么选择 3D 堆叠条形图代码实现:从数据到 3D 世界的搭建核心代码逐行解析细节优化应用场景:3D 堆叠图