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的方式的更多相关文章

  1. Android中多线程编程(三)Handler更新UI的方式

    Handler更新UI的方式和原因以及遇到的问题 1.方式: 仅仅能通过Handler来更新UI. 代码例如以下: package com.chengdong.su.handlerdemo; impo ...

  2. Android异步更新UI的四种方式

    Android异步更新UI的四种方式 2015-09-06 09:23 segmentfault 字号:T | T 大家都知道由于性能要求,android要求只能在UI线程中更新UI,要想在其他线程中 ...

  3. 拒绝卡顿——在WPF中使用多线程更新UI

    原文:拒绝卡顿--在WPF中使用多线程更新UI 有经验的程序员们都知道:不能在UI线程上进行耗时操作,那样会造成界面卡顿,如下就是一个简单的示例: public partial class MainW ...

  4. Android开发更新UI的几种方式

    1.runOnUiThread 2.handler post 3.handler sendmessage 4.view post xml布局文件: <RelativeLayout xmlns:a ...

  5. WPF多线程更新UI的一个解决途径

    那么该如何解决这一问题呢?通常的做法是把耗时的函数放在线程池执行,然后切回主线程更新UI显示.前面的updateTime函数改写如下: private async void updateTime()  ...

  6. 富客户端 wpf, Winform 多线程更新UI控件

    前言 在富客户端的app中,如果在主线程中运行一些长时间的任务,那么应用程序的UI就不能正常相应.因为主线程要负责消息循环,相应鼠标等事件还有展现UI. 因此我们可以开启一个线程来格外处理需要长时间的 ...

  7. 动态更新UI的方式

    1. TimerTask 和 timer连用: 这里主要是实现倒计时, TimerTask 里面有方法runOnUiThread,在这个方法里面调用timer cancel()停止倒计时,同样更新UI ...

  8. android Handler更新UI

    android中经常需要更新界面某个元素的值,但是在主线程中是不可以直接更新主线程的值.这里推荐通过handler机制来更新值. 一Handler的定义: 主要接受子线程发送的数据, 并用此数据配合主 ...

  9. Android 中更新UI的方法

    1)使用Activity.runOnUiThread(Runable action)方法 情景一: 在主线程中,定义方法,在方法中启动线程. public class MainActivity ext ...

随机推荐

  1. mysql语句中判断是否包含某字符串的方法

    当我们需要对数据做筛选和查询的时候,往往会涉及到一些限制条件的判断,今天就分享一个判断字符串的技巧. like 相信大家对like的用法肯定都很熟悉了,它可以匹配字段以某字符串开始,以某字符串结尾,包 ...

  2. 在Windows上安装和配置Jenkins

    一.windows上安装Jenkins 1.官网下载Jenkins安装包Jenkins.msi ,进入安装模式,选择默认配置,安装完成之后,就会默认打开浏览器 http://localhost:808 ...

  3. centeros 6 远程升级ssl ssh 的shell脚本

    变量说明 SSL_N=openssl-1.0.2p #ssl 版本SSH_N=openssh-7.9p1 #ssh 版本ZLIB_N=zlib-1.2.11 # zlib 版本 脚本分为两个,因为升级 ...

  4. wap学习记录

    针对移动端浏览器: 大部分的浏览器内核都是webkit内核,对h5和c3的支持非常好 库 国内比较流行的框架 : 妹子UI bootstrap中解决ie8以及以下的h5标签和媒体查询兼容问题的两个库分 ...

  5. js 函数节流和防抖

    js 函数节流和防抖 throttle 节流 事件触发到结束后只执行一次. 应用场景 触发mousemove事件的时候, 如鼠标移动. 触发keyup事件的情况, 如搜索. 触发scroll事件的时候 ...

  6. js中表格的相关操作

    tHead:表头 tBodies:表格正文 tFoot:表格尾 rows:行 cells:列 表格的应用: 1.获取 2.表格创建 3.隔行变色 4.删除一行 <!DOCTYPE html> ...

  7. 条款18:让接口容易被正确使用,不易被误用(Make interface easy to use correctly and hard to use incorrectly)

    NOTE : 1.好的接口容易被正确使用,不容易被误用.应该让所有接口努力达成这些性质. 2.“促进正确使用”的办法包括接口的一致性,以及内置类型的行为兼容. 3.“阻止误用”的办法包括建立新类型/限 ...

  8. python基础知识05-控制流程

    控制流程 1.条件判断 python中的代码从上到下执行. if 条件: 缩进 语句1 elif 条件2: 缩进 语句2 (…或者写pass关键字.不写任何代码的时候,防止报错.) ... else: ...

  9. linux 定时任务(注意事项)

    1.在要执行的脚本中,执行其他脚本时,需要加入其他脚本需要的环境变量. 2.路径要写全,绝对路径.命令要写全,使用绝对路径的方式.

  10. POJ 2377 (并查集+sort求最远路)

    Description Bessie has been hired to build a cheap internet network among Farmer John's N (2 <= N ...