主线程不能执行耗时的操作,子线程不能更新Ui
在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法:
在看方法之前看一下Android中消息机制:

Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
Handler:处理者,负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
MessageQueue:消息队列,用来存放Handler发送过来的消息,并按照FIFO规则执行。当然,存放Message并非实际意义的保存,而是将Message以链表的方式串联起来的,等待Looper的抽取。
Looper:消息泵,不断地从MessageQueue中抽取Message执行。因此,一个MessageQueue需要一个Looper。
Thread:线程,负责调度整个消息循环,即消息循环的执行场所。
不熟悉的朋友可以参考一下这篇文档:
Android知识梳理:消息机制之Handler:http://gqdy365.iteye.com/blog/2148925
Android知识梳理:消息机制之Looper :http://gqdy365.iteye.com/blog/2137494
下面基于上述原理说一下更新方法:
方法一:用Handler
1、主线程中定义Handler:
- Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- switch (msg.what) {
- case 0:
- //完成主界面更新,拿到数据
- String data = (String)msg.obj;
- updateWeather();
- textView.setText(data);
- break;
- default:
- break;
- }
- }
- };
2、子线程发消息,通知Handler完成UI更新:
- private void updateWeather() {
- new Thread(new Runnable(){
- @Override
- public void run() {
- //耗时操作,完成之后发送消息给Handler,完成UI更新;
- mHandler.sendEmptyMessage(0);
- //需要数据传递,用下面方法;
- Message msg =new Message();
- msg.obj = "数据";//可以是基本类型,可以是对象,可以是List、map等;
- mHandler.sendMessage(msg);
- }
- }).start();
- }
方法一的Handler对象必须定义在主线程中,如果是多个类直接互相调用,就不是很方便,需要传递content对象或通过接口调用;
方法二:用Activity对象的runOnUiThread方法更新
在子线程中通过runOnUiThread()方法更新UI:
- new Thread() {
- public void run() {
- //这儿是耗时操作,完成之后更新UI;
- runOnUiThread(new Runnable(){
- @Override
- public void run() {
- //更新UI
- imageView.setImageBitmap(bitmap);
- }
- });
- }
- }.start();
如果在非上下文类中(Activity),可以通过传递上下文实现调用;
- Activity activity = (Activity) imageView.getContext();
- activity.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- imageView.setImageBitmap(bitmap);
- }
- });
这种方法使用比较灵活,但如果Thread定义在其他地方,需要传递Activity对象;
方法三:View.post(Runnable r)
- imageView.post(new Runnable(){
- @Override
- public void run() {
- imageView.setImageBitmap(bitmap);
- }
- });
主线程不能执行耗时的操作,子线程不能更新Ui的更多相关文章
- 关于Handler的理解,子线程不能更新UI的纠正和回调的思考
开发Android这么久了,总会听到有人说:主线程不能访问网络,子线程不能更新UI.Android的主线程的确不能长时间阻塞,但是子线程为什么不能更新UI呢?今天把这些东西整理,顺便在子线程更新UI. ...
- Android多线程之(一)View.post()源码分析——在子线程中更新UI
提起View.post(),相信不少童鞋一点都不陌生,它用得最多的有两个功能,使用简便而且实用: 1)在子线程中更新UI.从子线程中切换到主线程更新UI,不需要额外new一个Handler实例来实现. ...
- android 不能在子线程中更新ui的讨论和分析
问题描写叙述 做过android开发基本都遇见过 ViewRootImpl$CalledFromWrongThreadException,上网一查,得到结果基本都是仅仅能在主线程中更改 ui.子线程要 ...
- 如何在子线程中更新UI
一:报错情况 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that creat ...
- Android在子线程中更新UI(二)
MainActivity如下: package cc.testui2; import android.os.Bundle; import android.view.View; import andro ...
- 使用Handler在子线程中更新UI
Android规定仅仅能在主线程中更新UI.假设在子线程中更新UI 的话会提演示样例如以下错误:Only the original thread that created a view hierach ...
- Android在子线程中更新UI(一)
MainActivity如下: package cc.testui1; import android.os.Bundle; import android.os.Handler; import andr ...
- Android开发UI之在子线程中更新UI
转自第一行代码-Android Android是不允许在子线程中进行UI操作的.在子线程中去执行耗时操作,然后根据任务的执行结果来更新相应的UI控件,需要用到Android提供的异步消息处理机制. 代 ...
- Android子线程中更新UI的4种方法
方法一:用Handler 1.主线程中定义Handler: Handler mHandler = new Handler() { @Override public void handleMessage ...
随机推荐
- 为什么我没有拔出钥匙 ——开锁引发的程序bug解决方案的思考
http://blog.csdn.net/wojiushiwo987/article/details/8851204为什么我没有拔出钥匙 ——开 ...
- Docker的安装使用-第1章
Docker的安装 1.1 环境说明 操作系统: Red Hat Enterprise Linux Server release 7.1 软件环境: 系统已经配置了yum安装源 软件版本: docke ...
- cat /proc/iomem
在proc目录下有iomem和ioports文件,其主要描述了系统的io内存和io端口资源分布. 对于外设的访问,最终都是通过读写设备上的寄存器实现的,寄存器不外乎:控制寄存器.状态寄存器和数据寄存器 ...
- Angularjs Directive - Compile vs. Link
如果我想实现这样一个功能,当一个input失去光标焦点时(blur),执行一些语句,比如当输入用户名后,向后台发ajax请求查询用户名是否已经存在,好有及时的页面相应. 输入 hellobug 失去 ...
- java synchronized究竟锁住的是什么
刚学java的时候,仅仅知道synchronized一个线程锁.能够锁住代码,可是它真的能像我想的那样,能够锁住代码吗? 在讨论之前先看一下项目中常见关于synchronized的使用方法: publ ...
- android.animation(1) - ValueAnimator的ofInt(), ofFloat(), addUpdateListener(), addListener()(转)
一.概述 long long ago,我写过几篇有关Animation的文章,讲解了传统的alpha.scale.translate.rotate的用法及代码生成方法.其实这三篇文章讲的所有动画效果叫 ...
- 怎么使用Less/Sass编译工具koala
怎么使用Less/Sass编译工具koala 如何使用Less/Sass编译工具koala 一.SASS调试插件的方法 如需调试功能,请在编译输出的时候输出debug信息,那样解析的css文件中就会包 ...
- Linux strace命令使用详解
strace是Linux环境下的一款程序调试工具,用来监察一个应用程序所使用的系统调用及它所接收的系统信息. 可谓是 linux 下的调试利器,不仅可以用来找程序错误,系统为什么挂死了,命令为什么报错 ...
- [转]SOA接口的两种常用实现比较:SOAP vs REST
原文链接:http://blog.csdn.net/zhaohuabing/article/details/39643127 SOA架构用于异构系统的协作,因此需要一种跨操作系统.跨语言的通用的消息交 ...
- nginx的root alias 指令
location /img/ { alias /var/www/image/; } #若按照上述配置的话,则访问/img/目录里面的文件时,ningx会自动去/var/www/image/目录找文件 ...