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. 360 Atlas中间件安装及使用

    1.下载Atlas wget https://github.com/Qihoo360/Atlas/releases/download/2.2.1/Atlas-2.2.1.el6.x86_64.rpm ...

  2. Python数据可视化库-Matplotlib(二)

    我们接着上次的继续讲解,先讲一个概念,叫子图的概念. 我们先看一下这段代码 import matplotlib.pyplot as plt fig = plt.figure() ax1 = fig.a ...

  3. day16-python之函数式编程匿名函数

    1.复习 #!/usr/bin/env python # -*- coding:utf-8 -*- name = 'alex' #name=‘lhf’ def change_name(): name= ...

  4. CSRF verification failed. Request aborted. 表单提交方法为POST时的报错

    本人所用Django版本为1.11,在设置请求方法为POST时,遇到标题中的错误,尝试了多种方法,最终通过下面的操作来修复: 在template文件中添加图中红框部分 接着,导入csrf_exempt ...

  5. python之 集合 学习笔记

    """ 集合内的元素是无序的,集合内的元素必须是可哈希的集合内元素的唯一的,不存在重复列表和字典不能存在集合里面,因为列表字典可变 可哈希集合也是不可哈希的 unhash ...

  6. 详解Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

  7. zoj 2736 Daffodil number

    Daffodil number Time Limit: 2 Seconds      Memory Limit: 65536 KB The daffodil number is one of the ...

  8. PHP include和require 区别

    require 的使用方法如 require("MyRequireFile.php"); .这个函数通常放在 PHP 程序的最前面,PHP 程序在执行前,就会先读入 require ...

  9. 匈牙利游戏(codevs 1269)

    题目描述 Description Welcome to the Hungary Games! The streets of Budapest form a twisted network of one ...

  10. centos下wget时提示unable to resolve host address ...

    网络正常的情况,可以查看/etc/resolv.conf [root@localhost ~]# more /etc/resolv.conf # Generated by NetworkManager ...