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 ...
随机推荐
- python:零散记录
1.rstrip()删除末尾指定字符串 例如:A = '1,2,3,4,5,' B = A.rstrip(',') B = '1,2,3,4,5' 2.isdigit()方法 Python isdig ...
- 条款19:设计class犹如设计TYPE(Treat class design as type design)
NOTE: 1.Class 的设计就是type的设计.在定义一个新type之前,请确认自己已经考虑过本条款所有主题(具体参考effective c++).
- tornado框架基础05-模板继承、UImodul和UImethods
01 模板继承 父模板 <html lang="en"> <head> <meta charset="UTF-8"> ...
- NGINX模块(二)
[Nginx标准HTTP模块] 一.HTTP核心模块 指令1:alias 语法:alias file-path|directory-path; 默认值:no 使用字段:location 说明:这个指令 ...
- BZOJ 3926: [Zjoi20150]诸神眷顾的幻想乡
3926: [Zjoi20150]诸神眷顾的幻想乡 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 438 Solved: 273 Descripti ...
- xtu read problem training A - Dividing
A - Dividing Time Limit:1000MS Memory Limit:10000KB 64bit IO Format:%I64d & %I64u Descri ...
- PTA 01-复杂度1 最大子列和问题 (20分)
题目地址 https://pta.patest.cn/pta/test/15/exam/4/question/709 5-1 最大子列和问题 (20分) 给定KK个整数组成的序列{ N_1N1 ...
- [luoguP2679] 子串(DP)
传送门 气死我了,自己YY的方法只能得70分. 一个下午都在搞这道题. 至于正解,真的不想写了. 请移步 here #include <cstdio> #define M 201 #def ...
- private、protected和public的区别
private 是完全私有的,只有当前类中的成员能访问到. protected 是受保护的,只有当前类的成员与继承该类的类才能访问. 这两个是访问类中成员权限的限制符.在类外如果想使用类中的成员,只能 ...
- Android: java.lang.ClassCastException: android.widget.imageView cannot be cast to android.widget.textView异常解决
有时在修改xml文件时,全报这种错误,这个应该是缓存没得到及时更新导致的,可以通过以下方法解决: Eclipse tends to mess up your resources every now a ...