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 ...
随机推荐
- excel组装sql
="INSERT INTO TABLE_XXXX (COLUMN_1, COLUMN_2, COLUMN_3, COLUMN_4, COLUMN_5, COLUMN_6, COLUMN_7, ...
- 解决Spellchecker inspection helps locate typos and misspelling in your code
idea出现这个是因为词库中没有这个单词,所以提示拼写错误 解决办法:双击下面有虚线的单词——>鼠标右键——>spelling——>save 'xxx' to distionary
- Django之使用celery异步完成发送验证码
使用celery的目的:将项目中耗时的操作放入一个新的进程实现 1.安装celery pip install celery 2.在项目的文件夹下创建包celery_tasks用于保存celery异步任 ...
- svn服务
svn服务实战应用指南 1.1 svn介绍 什么是svn? svn(sub-version)是近年来崛起的非常优秀的版本管理工具,与cvs管理工具一样,svn是一个跨平台的开源的版本控制系统, ...
- VMware搭建内网并通过iptables端口转发联网
整体流程图 配置Server1 新建两块网卡 一块网卡设置为桥接模式,另外一块设置为仅主机模式 查看两块网卡配置 root@ubuntu:~# ifconfig ens33 Link encap:Et ...
- 使用scrapy爬取suning
# -*- coding: utf-8 -*- import scrapy from copy import deepcopy class SuSpider(scrapy.Spider): name ...
- 【HIHOCODER 1478】 水陆距离(BFS)
描述 给定一个N x M的01矩阵,其中1表示陆地,0表示水域.对于每一个位置,求出它距离最近的水域的距离是多少. 矩阵中每个位置与它上下左右相邻的格子距离为1. 输入 第一行包含两个整数,N和M. ...
- loadrunner报错-持续更新
一.关联使用web_reg_save_param报错 1.以下是网页中需要关联的地方,有2处,通过网页查看源代码可以看: 2.还可以通过Generation Log来查看需要关联的地方: 3. 然后再 ...
- POJ3528移石头
题目大意: 河道两旁直线上有两块石头不能移动,距离为L,但中间放置了N块石头并列出这N块石头到起点的距离,可以移走M块,那么移走石头后每次牛跨石头的最小距离如何达到最大值,输出这个最大值 让最小距离的 ...
- [HNOI2004]宠物收养场(Treap)
洛谷传送门 这题真是恶心,一开始没理解题意. 原来如果有狗,狗就会存在收养场中,直到有人来领养: 如果有人,人也会存在收养场中,直到有狗来被领养. 就是建一个treap,狗来把狗插进去,人来后把狗领养 ...