在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法:

在看方法之前需要了解一下Android中的消息机制

转载请标明出处:http://blog.csdn.net/seu_calvin/article/details/52120389


方法1  Activity.runOnUiThread

方法如下:

runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText("Hello");
}
});

这种方法简单易用,如果当前线程是UI线程,那么行动是立即执行。如果当前线程不是UI线程,就发布到事件队列的UI线程。其实和Handler差不多,都是将这个更新UI的请求消息,加入到事件队列,等待主线程空闲的时候执行。

方法2  Handler

主线程中定义Handler如下:

Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
String data = (String)msg.obj;
textView.setText(data);
break;
default:
break;
}
}
};

子线程发消息,通知Handler完成UI更新,代码如下:

new Thread(new Runnable(){
@Override
public void run() {
//耗时操作
mHandler.sendEmptyMessage(0);
Message msg =new Message();
msg.obj = "数据";//可以是基本类型,可以是对象,可以是List、map等
mHandler.sendMessage(msg);
}
}).start();

方法3  View.post

final Button btn =(Button)findViewById(R.id.btn);
btn.post(new Runnable(){
@Override
publicvoid run() {
btn.setText("Hello");
}
});

上面的代码就是更新btn中的内容,同样下面的代码也可以达到这种效果。

Handler handler = new Handler();
final Button btn = (Button)findViewById(R.id.btn);
handler.post(new Runnable(){
@Override
public void run() {
btn.setText("Hello");
}
});

这个是用handler.post方法,一个是用View.post方法,handler.post方法已经在Android的消息机制中介绍过了,其实最终也是调用了方法2中的send方法。

现在看一下View.post方法的源代码:

public boolean post(Runnable action) {
Handler handler;
AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
handler = attachInfo.mHandler;
} else {
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}
return handler.post(action);
}

方法中主要的功能代码就是attachInfo.mHandler,获取当前线程(即UI线程)的Hanlder,然后将action对象post到Handler里。在Handler里的处理过程上面链接文已经分析的很清楚了,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。在Handler的dispatchMessage方法里,第一句话就是为它所设,直接调用runnable的run方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI。

方法4 广播

子线程中发送广播,主线程中接收广播并更新UI。

方法5  使用AsyncTask

为了简化子线程中访问UI,系统提供给了我们AsyncTask。

AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行进度和结果传递给主线程并更新UI。本质上来说AsyncTask封装了Thread和Handler,但是AsyncTask不适合进行特别耗时的后台任务,如果需要进行特别耗时的任务,建议使用线程池。

不同API版本的AsyncTask具有不同的表现,因此需要注意。为了控制篇幅,具体的AsyncTask的使用方法和工作原理,写在这篇文章,AsyncTask的使用以及源码解析,有兴趣的同学可以查看。

Android开发——子线程操作UI的几种方法的更多相关文章

  1. Android开发——子线程操作UI的几种方法(待续)

    方法2  Handler andler mHandler = new Handler() { @Override public void handleMessage(Message msg) { su ...

  2. Android通过子线程更新UI的几种方式

    一般情况下,UI的更新都少不了Handler,首先我们先了解一下Handler机制: Handler消息机制 定义 Message 线程间通信的数据单元,可通过message携带需要的数据创建对象:M ...

  3. iOS子线程更新UI的两种方法

    http://blog.csdn.net/libaineu2004/article/details/45368427 方法1:performSelectorOnMainThread[self perf ...

  4. iOS子线程操作UI问题检查

    iOS开发中,因为大部分函数都不是线程安全的,所以UI子线程中操作UI是非常危险的事,但是有时候因为开发者经验不足,不知道子线程中不能UI,或者知道但是写代码的时候没注意,或者不知道那些函数操作UI了 ...

  5. Android可以子线程更新UI?

    初了解Android的时候,就知道Android是不能在子线程更新UI的,不然程序会直接抛出异常,告诉你,别给我在自线程搞事情! 但是,这个是针对普通的view做的限制,而TextureView,Su ...

  6. android 解决子线程进行UI操作

    Android确实不允许在子线程中进行UI操作的,但我们有时必须在子线程里去执行一些耗时的任务,然后根据任务的执行结果来更新相应的UI控件. Android提供了一套异步消息处理机制,可以解决子线程中 ...

  7. android基础---->子线程更新UI

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

  8. C#子线程更新UI控件的方法总结

    http://blog.csdn.net/jqncc/article/details/16342121 在winform C/S程序中经常会在子线程中更新控件的情况,桌面程序UI线程是主线程,当试图从 ...

  9. 解决子线程操作UI的方法

随机推荐

  1. centos 6.x下pxe+tftp+http+kickstart无人值守安装操作系统

    1.1 什么是PXE PXE(Pre-boot Execution Environment,预启动执行环境)是由Intel公司开发的最新技术,工作于Client/Server的网络模式,支持工作站通过 ...

  2. Unity Shader入门精要学习笔记 - 第11章 让画面动起来

    转自 冯乐乐的 <Unity Shader入门精要> Unity Shader 中的内置变量 动画效果往往都是把时间添加到一些变量的计算中,以便在时间变化时画面也可以随之变化.Unity ...

  3. 一个页面有相同ID元素的情况分析

    经常会遇到一个页面中有相同定义相同id的情况,从道理上来说,id应该是这个页面中某个元素的唯一标识,所以不应该出现有相同id的情况,否则会产生意想不到的结果.而且各个浏览器的表现也是不一样的.我只做了 ...

  4. APACHE服务器httpd.exe进程占用cpu100%的解决方法

    httpd.exe进程占用cpu%100,关闭掉AppServ服务,cpu应用率立刻下降到0. 重新启动AppServ又出现占用cpu高的情况. 原因,httpd.exe和防火墙配置有冲突. 解决方法 ...

  5. 记住,永远不要在MySQL中使用“utf8”-转

    http://www.infoq.com/cn/articles/in-mysql-never-use-utf8-use-utf8 最近我遇到了一个bug,我试着通过Rails在以“utf8”编码的M ...

  6. Java GUI setSize()、setPreferredSize()的区别

    setSize().setPreferredSize()都可以设置组件的大小,但二者的使用有所不同. 1.setSize()的使用方式 setSize(int width,int height) se ...

  7. 初识react中的状态量

    react组件中的两类状态数据:props,state,官网API给出的使用规范,多读几遍,受益匪浅: 结论: 1. 对应任何可变的数据,理应只有一个单一“ 数据源 ” 2. 如果多个组件均需要这些数 ...

  8. RK3288开发过程中遇到的问题点和解决方法之Packages

    去除桌面渐变黑边 Launcher3/.../Launcher.java SETWorkspaceBackground => setWorkspaceBackground 注释boolean i ...

  9. ZOJ 3627 Treasure Hunt II (贪心,模拟)

    题意:有n个城市并排着,每个城市有些珠宝,有两个人站在第s个城市准备收集珠宝,两人可以各自行动,但两人之间的距离不能超过dis,而且每经过一个城市就需要消耗1天,他们仅有t天时间收集珠宝,问最多能收集 ...

  10. 洛谷 P2936 [USACO09JAN]全流Total Flow

    题目描述 Farmer John always wants his cows to have enough water and thus has made a map of the N (1 < ...