Android多线程更新UI的方式
Android下,对于耗时的操作要放到子线程中,要不然会残生ANR,本次我们就来学习一下Android多线程更新UI的方式。
首先我们来认识一下anr:
anr:application not reponse:应用程序无响应
主线程:UI线程
anr产生的原因:主线程需要做很多重要的事情,响应点击事件,更新ui,如果在主线程里面阻塞时间过久,应用程序就会无响应,为了避免应用程序出现anr,所有的耗时的操作,都应该放在子线程中执行。
认识了anr后,我们就来学习一下怎样在Android下开启多线程,并更新ui了。一共有两种方式:
第一种采用:Handler。
Handler获取当前线程中的looper对象,looper用来从存有Message的Message Queue里取出message,再由Handler进行message的分发和处理。
handler进制的原理:
android提供了handler和looper来满足线程间的通信。Handler先进先出原则。looper用来管理特定线程内对象之间的消息交换(message Exchange).
1)looper:一个线程可以产生一个looper对象,由它来管理此线程里的message queue(消息队列)
2)handler:你可以构造一个handler对象来与looper沟通,以便push新消息到messagequeue里;或者接收looper(从messagequeue里取出)所送来的消息。
我们使用的时候呢,需要在子线程中定义message,并把要返回的obj对象,传递给msg,同时由于handler不止要处理这一种类型,所以我们还要定义what的类型,以便让handler分类处理。
Message msg = new Message();
msg.what = CHANGE_UI;
msg.obj = result;
handler.sendMessage(msg);
好的接下来我们就实例来使用handler。
new Thread(){
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setRequestProperty("User-Agent", "");
int code = conn.getResponseCode();
if(code==200){
InputStream is = conn.getInputStream();
String result = StreamTools.readInputStream(is);
//tv_content.setText(result);
Message msg = new Message();
msg.what = CHANGE_UI;
msg.obj = result;
handler.sendMessage(msg);
}else{
Message msg = new Message();
msg.what = ERROR;
handler.sendMessage(msg);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Message msg = new Message();
msg.what = ERROR;
handler.sendMessage(msg);
}
};
}.start();
这里采用的 StreamTools.readInputStream的实现是这样的,目的是把输入流转化为字符串。
/**
* 把输入流转化为字符串
* @param is
* @return
*/
public static String readInputStream(InputStream is){
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = 0;
byte[] buffer = new byte[1024];
while((len = is.read(buffer))!=-1){
baos.write(buffer,0,len);
}
is.close();
baos.close();
byte[] result = baos.toByteArray(); //试着解析网址返回的字符串,
String temp = new String(result);
if(temp.contains("utf-8")){
return temp;
}else if(temp.contains("gbk")){
return new String(result,"gbk");
} return temp;
//return new String(result);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "获取失败";
} }
其中handler的实现是这样的。
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case ERROR:
Toast.makeText(MainActivity.this, "获取数据失败", 0).show();
break;
case CHANGE_UI:
tv_content.setText(msg.obj+"");
Toast.makeText(MainActivity.this, "获取数据失败", 0).show();
break;
}
};
};
这样呢,我们便可以用handler,也即消息处理机制来更新UI了,
第二种方式。
采用runOnUiThread(new Runnable()),这要实现Runnable借口,我们可以直接在这个线程中进行UI的更新。是api提供的方法,较为便捷。
new Thread(){
@Override
public void run() {
final String result = LoginServices.loginByGet(username, password);
if(result != null){
//成功
runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, result, 0).show();
}
});
}else{
//请求失败
runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "请求失败", 0).show();
}
});
}
};
}.start();
源码:https://github.com/darren90/ChengeUI
作者:Darren
微博:@IT_攻城师
出处:http://www.cnblogs.com/fengtengfei/
Android多线程更新UI的方式的更多相关文章
- Android中多线程编程(三)Handler更新UI的方式
Handler更新UI的方式和原因以及遇到的问题 1.方式: 仅仅能通过Handler来更新UI. 代码例如以下: package com.chengdong.su.handlerdemo; impo ...
- Android异步更新UI的四种方式
Android异步更新UI的四种方式 2015-09-06 09:23 segmentfault 字号:T | T 大家都知道由于性能要求,android要求只能在UI线程中更新UI,要想在其他线程中 ...
- 拒绝卡顿——在WPF中使用多线程更新UI
原文:拒绝卡顿--在WPF中使用多线程更新UI 有经验的程序员们都知道:不能在UI线程上进行耗时操作,那样会造成界面卡顿,如下就是一个简单的示例: public partial class MainW ...
- Android开发更新UI的几种方式
1.runOnUiThread 2.handler post 3.handler sendmessage 4.view post xml布局文件: <RelativeLayout xmlns:a ...
- WPF多线程更新UI的一个解决途径
那么该如何解决这一问题呢?通常的做法是把耗时的函数放在线程池执行,然后切回主线程更新UI显示.前面的updateTime函数改写如下: private async void updateTime() ...
- 富客户端 wpf, Winform 多线程更新UI控件
前言 在富客户端的app中,如果在主线程中运行一些长时间的任务,那么应用程序的UI就不能正常相应.因为主线程要负责消息循环,相应鼠标等事件还有展现UI. 因此我们可以开启一个线程来格外处理需要长时间的 ...
- 动态更新UI的方式
1. TimerTask 和 timer连用: 这里主要是实现倒计时, TimerTask 里面有方法runOnUiThread,在这个方法里面调用timer cancel()停止倒计时,同样更新UI ...
- android Handler更新UI
android中经常需要更新界面某个元素的值,但是在主线程中是不可以直接更新主线程的值.这里推荐通过handler机制来更新值. 一Handler的定义: 主要接受子线程发送的数据, 并用此数据配合主 ...
- Android 中更新UI的方法
1)使用Activity.runOnUiThread(Runable action)方法 情景一: 在主线程中,定义方法,在方法中启动线程. public class MainActivity ext ...
随机推荐
- 第六天,字典Dictionary
字典(Dictionary)在Python中是一种可变的容器模型,它是通过一组键(key)值(value)对组成,这种结构类型通常也被称为映射,或者叫关联数组,也有叫哈希表的.每个key-value之 ...
- jquery ajax示例
$.ajax({ type: "POST",//方法类型 dataType: "json",//预期服务器返回的数据类型 url: "${ctx }/ ...
- LeetCode(52) N-Queens II
题目 Follow up for N-Queens problem. Now, instead outputting board configurations, return the total nu ...
- Counting Kangaroos is Fun 求最少可见袋鼠数
Description There are n kangaroos with pockets. Each kangaroo has a size (integer number). A kangaro ...
- 3.3.3 使用 join 连接字段
join 命令可以将多个文件结合在一起,每个文件里的每条记录,都共享一个键值(key),键值指的是记录中的主字段,通常会是用户名称.个人姓氏.员工编号之类的数据.举例来说,两个文件,一个列出所 ...
- 解决hibernate产生的id序列或者setXX不能同步到数据库到问题(this.hibernateTemplate.flush();hibernateTemplate.getSessionFactory().getCurrentSession().connection().commit())
通过WarehouseInventoryPreLog warehouseInventoryPreLog = new WarehouseInventoryPreLog();产生一个id序列 如果不flu ...
- CEF与代理
此文已由作者王荣涛授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. CEF(Chromium Embedded Framework)如今已经广泛被应用于客户端软件,网易内部就有 ...
- HTTP API 自动化测试从手工测试到平台的演变
不管是 Web 系统,还是移动 APP,前后端逻辑的分离设计已经是常态化,相互之间通过 API 调用进行数据交互.在基于 API 约定的开发模式下,如何加速请求 / 响应的 API 测试,让研发人员及 ...
- iview自定义配置
说明 iview是一套基于 Vue.js 的高质量 UI 组件库.主要用户PC端页面设计. 官网:https://www.iviewui.com/ 1.在vue-cli项目中,添加该框架 第一步,安装 ...
- spring security3.1升级到4.1问题(1)访问/j_spring_security_check 404
升级完后,发现登录不进去,把post改成get好了,但是系统的提交表单功能都不能用了,也是解决了很长时间,最后找到了根本原因. spring sercurity 4.0 csrf保护是默认开启的,cs ...