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

目录

一,Android中的多线程问题

1.模拟耗时工作

2.Android开启子线程 

 二,在子线程中更新UI

1.异步消息处理机制 Handler

2.使用runOnUiThread更新UI


一,Android中的多线程问题

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

1.模拟耗时工作

        例如下面这段访问百度界面的代码,如果在主线程中运行的话就会出现android.os.Network-OnMainThreadException的报错,也就是在主线程中请求了网络操作,这是一种耗时操作。为了解决这个问题,就需要把操作放在子线程中运行。

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViews();setListeners();
}
private void setListeners() {btn_baidu.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {//获取百度链接URL url = new URL("https://www.baidu.com/");//获取输入流InputStream inputStream = url.openStream();byte[] bytes = new byte[1024];//存储输入的信息StringBuffer buffer = new StringBuffer();while((inputStream.read(bytes)) != -1){String str = new String(bytes, 0, bytes.length);buffer.append(str);}Log.i("baidu", buffer.toString());//关闭流inputStream.close();} catch (MalformedURLException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}});
}

2.Android开启子线程 

         在Android中开启线程的操作与在Java中一致,继承Thread类或实现Runnable接口,不了解的话可以阅读博客:Java线程基础:Thread Runnable 多线程 Synchronized 死锁...-CSDN博客。

例如下面用实现Runnable接口的方法来开启子线程,访问百度:

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViews();setListeners();
}
private void setListeners() {btn_baidu.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {new Thread(new Runnable() {@Overridepublic void run() {try {//获取百度链接URL url = new URL("https://www.baidu.com/");//获取输入流InputStream inputStream = url.openStream();byte[] bytes = new byte[1024];//存储输入的信息StringBuffer buffer = new StringBuffer();while((inputStream.read(bytes)) != -1){String str = new String(bytes, 0, bytes.length);buffer.append(str);}//在子线程中更改Ui界面,使用runOnUiThreadLog.i("baidu", buffer.toString());//关闭流inputStream.close();} catch (MalformedURLException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}}).start();}});
}

运行并查看日志,可以发现成功访问: 

 二,在子线程中更新UI

        使用子线程解决异步执行又会带来新问题,那就是在Android中,只有UI线程(也叫主线程)可以更新UI界面,子线程不能更新。为了在子线程中更新UI,我们需要使用Android异步消息处理机制

1.异步消息处理机制 Handler

        Android中的异步消息处理主要由4个部分组成:Message,Handler,MessageQueue,Looper。

  1. Message:在线程之间传递的消息,Message中可以封装一些数据如:what(int型,表示Message的编号),obj(封装的Object对象),此外还有int型的arg1,arg2等;
  2. Handler:用于在线程间发送和处理消息,发送消息使用sendMessage()方法,处理消息使用handleMessage()方法;
  3. MessageQueue:消息队列,用于存放Handler发送的消息,这些消息直到被处理前,会一直存放在消息队列中。每个线程只会有一个MessageQueue对象;
  4. Looper:Looper是每个线程中MessageQueue的管家,调用Looper的loop方法后,会进入无限循环,每当发现MessageQueue中存在一条消息,就会将其取出,并传递到Handler的handleMessage()方法中,每个线程只会有一个Looper对象; 

 异步消息处理机制的基本流程为:

(1)首先在主线程中创建一个Handler对象,并重写handleMessage方法。

(2)当子线程需要更改UI时,就创建一个Message对象,并通过Handler将Message发送出去,Message消息会被添加到MessageQueue中等待处理,Looper会一直尝试从消息队列中取出消息,并传给Handler的handleMessage方法。

(3)Handler的构造器中我们传入了Looper.getMainLooper,所以handleMessage方法中的代码会在UI线程中运行,我们就可以放心地进行UI操作。

下面是代码实例(获取网络图片):

private void getImg() {//1.在主线程中创建一个Handler对象,并重写handleMessage方法。Handler handler = new Handler(Looper.getMainLooper()){@Overridepublic void handleMessage(@NonNull Message msg) {switch (msg.what){case 114514:Bitmap bitmap = (Bitmap) msg.obj;iv_img.setImageBitmap(bitmap);Log.i("114514", "获取图片成功!");break;}}};//设置监听btn_getimg.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {new Thread(new Runnable() {@Overridepublic void run() {try {//2.当子线程需要更改UI时,就创建一个Message对象URL url = new URL("https://profile-avatar.csdnimg.cn/8e4c56733fdd4dda90854384976d4bb0_ih_lzh.jpg!1");InputStream inputStream = url.openStream();Bitmap bitmap = BitmapFactory.decodeStream(inputStream);Message msg = handler.obtainMessage();//封装bitmap对象和设置对象编号msg.obj = bitmap;msg.what = 114514;//3.通过Handler将Message发送出去handler.sendMessage(msg);inputStream.close();} catch (MalformedURLException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}}).start();}});
}

2.使用runOnUiThread更新UI

        runOnUiThread,在UI线程上运行指定的操作。如果当前线程是UI线程,则执行操作,如果当前线程不是UI线程,操作将被提交到UI线程的消息队列MessageQueue中。runOnUiThread只能在Activity中使用。

public final void runOnUiThread(Runnable action) {if (Thread.currentThread() != mUiThread) {mHandler.post(action);//提交到消息队列} else {action.run();//操作执行}}

还是上面获取图片的例子,将Handler改为使用runOnUiThread更改UI:

private void getImg() {//设置监听btn_getimg.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {new Thread(new Runnable() {@Overridepublic void run() {try {URL url = new URL("https://profile-avatar.csdnimg.cn/8e4c56733fdd4dda90854384976d4bb0_ih_lzh.jpg!1");InputStream inputStream = url.openStream();Bitmap bitmap = BitmapFactory.decodeStream(inputStream);runOnUiThread(new Runnable() {@Overridepublic void run() {iv_img.setImageBitmap(bitmap);}});} catch (MalformedURLException e) {throw new RuntimeException(e);} catch (IOException e) {throw new RuntimeException(e);}}}).start();}});
}

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

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

相关文章

免费ssl通配符证书申请教程

在互联网安全日益受到重视的今天,启用HTTPS已经成为网站运营的基本要求。它不仅保障用户数据传输的安全,提升搜索引擎排名,还能增强用户对网站的信任。通配符证书是一种SSL/TLS证书,用于同时保护一个域名及其所有下一级子域名的安…

CSS基础:display的3个常见属性值详解

你好,我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃-大专生,一枚程序媛,感谢关注。回复 “前端基础题”,可免费获得前端基础 100 题汇总,回复 “前端工具”,可获取 Web 开发工具…

Flutter第九弹 构建列表元素间距

目标: 1)Flutter Widget组件之间间距怎么表示? 2)列表怎么定义子项之间间距? 一、间距的表示组件 列表组件的间距一般采用固定间距,间距占据可见的空间。 已经使用的表示间距的组件 Spacer&#xff1a…

MATLAB实现遗传算法优化公铁水联运

公铁水联运是运输行业的经典问题, 常用智能算法进行优化,比如遗传算法. 公铁水多式联运优化的数学模型如下: 1.模型简介 公铁水多式联运优化问题可以抽象为一个网络流问题,其中节点代表不同的运输方式转换点(如公路、铁路、水运的交汇点&a…

x264编码器 MV 预测

H264 编码标准中MV预测的目的 每个分割 MV 的编码需要相当数目的比特,特别是使用小分割尺寸时。为减少传输比特数,可利用邻近分割的 MV 较强的相关性,MV 可由邻近已编码分割的 MV 预测而得。预测矢量 MVp 基于已计算 MV 和 MVD(预测与当前的差异)并被编码和传送。MVp 则取决…

【C++航海王:追寻罗杰的编程之路】C++11(上)

目录 1 -> C11简介 2 -> 统一的列表初始化 2.1 -> {}初始化 2.2 -> std::initializer_list 3 -> 声明 3.1 -> auto 3.2 -> decltype 3.3 -> nullptr 1 -> C11简介 在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1),使得C…

解决跨域和https不能访问的问题。

本地安装了项目,是一键安装的,安装之后还是apache的web服务器,有个视频服务用的是https的服务,要对这个项目进行二次开发,本地调用没问题,可是别人已调用就跨域。只能本地访问。 现在有两个问题:1.解决跨域问题 2.还要解决https访问的问题。 解决思路,用nginx 的ssl证…

网络编程套接字(三)之TCP服务器简单实现

目录 一、服务端TcpServer 1、tcp_server.hpp 2、tcp_server.cc 二、客户端TcpClient tcp_client.cc 三、服务器和客户端进行通信 四、完整代码 一、服务端TcpServer 首先我们需要对服务端进行封装。我们需要的成员变量有IP地址,端口号port,以及监…

CentOS7下安装mysql8或者mysql5.7

mysql8 1、下载 访问mysql官网下载mysql8软件包 https://dev.mysql.com/downloads/mysql/ 选择相应的版本如:RPM Bundle mysql-8.0.33-1.el7.x86_64.rpm-bundle.tar RPM Bundle 8.0.33 下载地址:https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.…

Android的一些总结

先打开自定义的app显示欢迎->消失 打开桌面应用程序->在桌面应用程序中也要能一键启动打开视频播放的app 桌面应用程序广播接收者进行监听,然后打开服务/activity是可行的。 ########################## 日志,调试: Usb 无线 串口…

Vue3从入门到实战:深度了解相关API

shallowRef 作用:创建一个响应式数据,但只对顶层属性进行响应式处理。 用法: let myVar shallowRef(initialValue); 特点:只跟踪引用值的变化,不关心值内部的属性变化。 shallowReactive 作用:创建一个…

【MySQL】表的基本约束

文章目录 1、约束类型1.1NOT NULL约束1.2UNIQUE:唯一约束1.3DEFAULT:默认值约束1.4PRIMARY KEY:主键约束1.5FOREIGN KEY:外键约束 2、表的设计2.1一对一2.2一对多2.3多对多 1、约束类型 关键字解释NOT NULL指示某列不能存储NULL值…

在线编辑器 CodeMirror

如何优雅的在网页显示代码 如果开发在线编辑器 引入资源&#xff1a; <link rel"stylesheet" href"https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.60.0/codemirror.min.css"><script src"https://cdnjs.cloudflare.com/ajax/libs/c…

力扣经典150题第三十题:长度最小的子数组

目录 力扣经典150题解析之三十&#xff1a;长度最小的子数组1. 介绍2. 问题描述3. 示例4. 解题思路方法一&#xff1a;滑动窗口 5. 算法实现6. 复杂度分析7. 测试与验证测试用例设计测试结果分析 8. 进阶9. 总结10. 参考文献感谢阅读 力扣经典150题解析之三十&#xff1a;长度最…

Web前端 Javascript笔记6

BOM 前面的笔记讲的都是DOM&#xff08;文档对象模型&#xff09;&#xff0c;DOM几乎被所有浏览器支持&#xff0c;是DOM的作用为操作HTML文档的重要手段。利用DOM可以对HTML文档中的所有元素&#xff0c;节点进行获取与访问&#xff0c;对标签属性与样式进行设置。 下面是一…

OpenHarmony鸿蒙南向开发案例:【智能窗户通风设备】

样例简介 本文档介绍了安全厨房案例中的相关智能窗户通风设备&#xff0c;本安全厨房案例利用轻量级软总线能力&#xff0c;将两块欧智通V200Z-R/BES2600开发板模拟的智能窗户通风设备和燃气告警设备组合成。当燃气数值告警时&#xff0c;无需其它操作&#xff0c;直接通知软总…

Targeted influence maximization in competitive social networks

abstract 利用口碑效应的广告对于推销产品是相当有效的。在过去的十年中&#xff0c;人们对营销中的影响力最大化问题进行了深入的研究。影响力最大化问题旨在将社交网络中的一小群人识别为种子&#xff0c;最终他们将引发网络中最大的影响力传播或产品采用。在网络营销的实际场…

C++ 继承(一)

一、继承的概念 继承是面向对象编程中的一个重要概念&#xff0c;它指的是一个类&#xff08;子类&#xff09;可以从另一个类&#xff08;父类&#xff09;继承属性和方法。子类继承父类的属性和方法后&#xff0c;可以直接使用这些属性和方法&#xff0c;同时也可以在子类中…

DLT 直接线性变换

DLT 直接线性变换 对于单应变换 x i ′ H x i x_i^{\prime}Hx_i xi′​Hxi​&#xff0c;易知两图中对应的特征点&#xff0c;如何找出所需要的 H H H​&#xff0c;为了解决这个问题&#xff0c;可以采用DLT算法 原理 其中采用Least Squares Error去拟合 其中目标是获得最佳…

【办公类-22-05】20240419 UIBOT填写“PATHS课程”的《SSBS校园行为问卷》

背景需求&#xff1a; 每年都有一个PATHS课程的“家长问卷调查”和“教师问卷调查”需要填写 作为教师&#xff0c;每次要对全班所有的孩子进行评价&#xff0c;每位孩子64题&#xff01; 反复点题目&#xff0c;感觉非常累&#xff0c;工作操作就是两位老师&#xff0c;每人做…