详解android异步更新UI的几种方法
作者:宿罪 发布时间:2022-03-07 08:27:22
前言
我们知道在Android开发中不能在非ui线程中更新ui,但是,有的时候我们需要在代码中执行一些诸如访问网络、查询数据库等耗时操作,为了不阻塞ui线程,我们时常会开启一个新的线程(工作线程)来执行这些耗时操作,然后我们可能需要将查询到的数据渲染到ui组件上,那么这个时候我们就需要考虑异步更新ui的问题了。
android中有下列几种异步更新ui的解决办法:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
long) View.postDelayed(Runnable, long)
使用handler(线程间通讯)(推荐)
AsyncTask(推荐)
对于下面这段代码:
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
mImageView.setImageBitmap(bitmap);
}
}).start();
}
这段代码是一个按钮点击事件的响应方法,当点击了这个按钮后开启了一个子线程去网络上加载图片,然后在这个线程中给imageView设置了图片(更新了ui),这段代码在非ui线程中更新了ui,运行会引发错误。
1. Activity.runOnUiThread:
通常,在Activity,我们可以使用Activity的runOnUiThread方法来更新ui。
如:
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
runOnUiThread(new Runnable() {
@Override
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
2. View.post(Runable)
View类及其子类提供了一个post(Runable)方法允许我们将我们要做的操作放到这个匿名Runable对象的run方法中,在这个方法里面我们可以直接更新ui。
如:
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
imageView.post(new Runnable() {
@Override
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
3. long) View.postDelayed(Runnable, long)
和View.post(Runable)方法一样,只是延迟第二个参数指定的时间后执行,而View.post(Runable)是立即执行。
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
imageView.postDelayed(new Runnable() {
@Override
public void run() {
mImageView.setImageBitmap(bitmap);
}
},2000);
}
}).start();
}
4. 使用Handler(推荐)
前面说道的几种方法当这种操作过多的时候,我们的代码会显得臃肿,代码及业务都难于管理控制,所以,当这类代码多的时候我们就应该采取Handler的方式了。
如:
new Thread(new Runnable() {
public void run() {
Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
Message message = mHandler.obtainMessage();
message.what = 1;
message.obj = bitmap;
mHandler.sendMessage(message);
}
}).start();
Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 1:
Bitmap bitmap = (Bitmap) msg.obj;
imageView.setImageBitmap(bitmap);
break;
case 2:
// ...
break;
default:
break;
}
}
};
5. AsyncTask(推荐)
android为我们提供了异步任务AsyncTask,我们可以使用AsyncTask轻松地实现异步加载数据及更新ui。
如:
AsyncTask<String,Void,Bitmap> asyncTask = new AsyncTask<String, Void, Bitmap>() {
/**
* 即将要执行耗时任务时回调,这里可以做一些初始化操作
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
}
/**
* 在后台执行耗时操作,其返回值将作为onPostExecute方法的参数
* @param params
* @return
*/
@Override
protected Bitmap doInBackground(String... params) {
Bitmap bitmap = loadImageFromNetwork(params[0]);
return bitmap;
}
/**
* 当这个异步任务执行完成后,也就是doInBackground()方法完成后,
* 其方法的返回结果就是这里的参数
* @param bitmap
*/
@Override
protected void onPostExecute(Bitmap bitmap) {
imageView.setImageBitmap(bitmap);
}
};
asyncTask.execute("http://example.com/image.png");
需要知道的是doInBackground方法工作在工作线程中,所以,我们在这个方法里面执行耗时操作。同时,由于其返回结果会传递到onPostExecute方法中,而onPostExecute方法工作在UI线程,这样我们就在这个方法里面更新ui,达到了异步更新ui的目的。
事实上,对于android的异步加载数据及更新ui,我们不仅可以选择AsyncTask异步任务,还可以选择许多开源的网络框架,如xUtils,Volley,Okhttp,…,这些优秀的网络框架让我们异步更新ui变得非常简单,而且,效率和性能也非常高。
总结:
对于上面的许多解决办法,其实它们做的都是同一件事情,即在工作线程中执行耗时任务,然后在ui线程中更新ui,只不过过程不一样,有得直接给我们封装好了,有得需要我们自己控制管理。
来源:http://blog.csdn.net/ydxlt/article/details/51247822
猜你喜欢
- Java程序设计 图形用户界面 【九】单选按钮单选按钮 JRadioButtonJRadioButton类方法作用public JRadio
- 前言apollo配置经常使用的方式是@value,比较便捷,如果只出现在一个类中还行,但是如果多个类中并不是很方便,特别是如果出现配置值变化
- 效果展示如下所示:实时监控redis环境信息和日志列表Redis配置在windows下安装的redis,在安装目录找到redis.windo
- 本文实例为大家分享了Unity3D实现旋钮控制灯光效果的具体代码,供大家参考,具体内容如下前言实际上使用的是非常简单的方式,通过开启以及关闭
- CSDN 的小伙伴们,大家好,我是沉默王二。重写(Overriding)算是 Java 中一个非常重要的概念,理解重写到底是什么对每个 Ja
- 1.算法效率算法效率分析分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,而空间效率被称作空间复杂度。时间复杂度主要衡
- 前言 分享到微信朋友圈的功能早已经有了,但微信登录推出并不久,文档写的也并不是很清楚,这里记录分享一下。 正文 
- 最近在做一个“温湿度控制”的项目,项目要求通过用户设定的温湿度数值和实时采集到的数值进行比对分析,因为数据的对比与分析是一个通过前端页面控制
- 本文实例为大家分享了C#实现网页画图的具体代码,供大家参考,具体内容如下代码贴着保存下using System;using System.C
- 本文介绍了spring cloud Feign使用中遇到的问题总结,分享给大家,具体如下:问题一:在前面的示例中,我们讲过@RequestM
- 场景做一个消息中心,专门负责发送消息。消息分为几种渠道,包括手机通知(Push)、短信(SMS)、邮件(Email),Websocket等渠
- ①概念二叉搜索树又称二叉排序树,它或者是一棵空树**,或者是具有以下性质的二叉树:若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
- 背景我们项目一开始的所有提示都是中文,后来要做国际化。发现项目中的带双引号的中文居然有 2.3 w 多条!!!简直让人欲
- 先说一句:密码是无法解密的。大家也不要再问松哥微人事项目中的密码怎么解密了!密码无法解密,还是为了确保系统安全。今天松哥就来和大家聊一聊,密
- 效果图如下:1.适用需求后台生成验证码,用于登陆验证。2. 功能实现所需控件/文件:无(普通标签)3.功能点实现思路1)前台思路:(1)前台
- 前言:上篇C#进阶系列——WebApi接口传参不再困惑:传参详解介绍了WebApi参数的传递,这篇来看看WebApi里面异常的处理。关于异常
- .ini 文件是Initialization File的缩写,即初始化文件,是windows的系统配置文件所采用的存储格式,统管window
- 一、将已经编译后的java中Class文件进行打包;打包命令JAR 如:将某目录下的所有class文件夹全部进行打包处理;使用的命令:jar
- 当我提交项目输入中文描述信息的时候,发现IDEA 的 Terminal无法显示中文信息,显示的是下面这样的因为我的终端设置了git.bash
- 一,项目简介经过调查研究进行开发设计的这款仓库管理系统,主要是为商家提供商品货物进销存的信息化管理,以便让商家在竞争如此激烈的今天占据一定的