Android开发之子线程操作UI的几种方法

在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法:

在看方法之前需要了解一下Android中的消息机制。

方法1 Activity.runOnUiThread

方法如下:

runOnUiThread(new Runnable() {
@Override
public void run() {
tv.setText("Hello");
}
}); 

这种方法简单易用,如果当前线程是UI线程,那么行动是立即执行。如果当前线程不是UI线程,就发布到事件队列的UI线程。其实和Handler差不多,都是将这个更新UI的请求消息,加入到事件队列,等待主线程空闲的时候执行。

方法2 Handler

主线程中定义Handler如下:

Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 0:
String data = (String)msg.obj;
textView.setText(data);
break;
default:
break;
}
}
}; 

子线程发消息,通知Handler完成UI更新,代码如下:

new Thread(new Runnable(){
@Override
public void run() {
//耗时操作
mHandler.sendEmptyMessage(0);
Message msg =new Message();
msg.obj = "数据";//可以是基本类型,可以是对象,可以是List、map等
mHandler.sendMessage(msg);
}
}).start(); 

方法3 View.post

final Button btn =(Button)findViewById(R.id.btn);
btn.post(new Runnable(){
@Override
publicvoid run() {
btn.setText("Hello");
}
}); 

上面的代码就是更新btn中的内容,同样下面的代码也可以达到这种效果。

Handler handler = new Handler();
final Button btn = (Button)findViewById(R.id.btn);
handler.post(new Runnable(){
@Override
public void run() {
btn.setText("Hello");
}
}); 

这个是用handler.post方法,一个是用View.post方法,handler.post方法已经在Android的消息机制中介绍过了,其实最终也是调用了方法2中的send方法。

现在看一下View.post方法的源代码:

public boolean post(Runnable action) {
Handler handler;
AttachInfo attachInfo = mAttachInfo;
if (attachInfo != null) {
handler = attachInfo.mHandler;
} else {
// Assume that post will succeed later
ViewRootImpl.getRunQueue().post(action);
return true;
}
return handler.post(action);
} 

方法中主要的功能代码就是attachInfo.mHandler,获取当前线程(即UI线程)的Hanlder,然后将action对象post到Handler里。在Handler里的处理过程上面链接文已经分析的很清楚了,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。在Handler的dispatchMessage方法里,第一句话就是为它所设,直接调用runnable的run方法。而此时,已经路由到UI线程里,因此,我们可以毫无顾虑的来更新UI。

方法4 广播

子线程中发送广播,主线程中接收广播并更新UI。

方法5 使用AsyncTask

为了简化子线程中访问UI,系统提供给了我们AsyncTask。

AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行进度和结果传递给主线程并更新UI。本质上来说AsyncTask封装了Thread和Handler,但是AsyncTask不适合进行特别耗时的后台任务,如果需要进行特别耗时的任务,建议使用线程池。

不同API版本的AsyncTask具有不同的表现,因此需要注意。为了控制篇幅,具体的AsyncTask的使用方法和工作原理,我打算后面单独成文进行介绍。

以上所述是小编给大家介绍的Android开发之子线程操作UI的几种方法,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

时间: 2016-08-04

android开发教程之子线程中更新界面

每个Handler对象与创建它的线程相关联,并且每个Handler对象只能与一个线程相关联.Handler一般有两种用途:1)执行计划任务,你可以再预定的实现执行某些任务,可以模拟定时器.2)线程间通信.在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息.当你创建子线程时,你可以再你的子线程中拿到父线程中创建的Handler对象,就可以通过该对象向父线程的消息队列发送消息了.由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面.

Android中检测当前是否为主线程最可靠的解决方法

如果在Android中判断某个线程是否是主线程?对于这个问题,你可能说根据线程的名字,当然这个可以解决问题,但是这样是最可靠的么?万一某天Google一下子将线程的名字改称其他神马东西呢. 方法揭晓 下面的方法是最可靠的解决方案. 复制代码 代码如下: public static boolean isInMainThread() {       return Looper.myLooper() == Looper.getMainLooper(); } 实际上,写到这里就基本解决了文章标题的问题了

Android Handler主线程和一般线程通信的应用分析

Handler的定义:主要接受子线程发送的数据, 并用此数据配合主线程更新UI.解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发, 比如说, 你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作.如果此时需要一个耗时的操作,例如: 联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象, 如果5秒钟还没有完成的话,会

Android中子线程和UI线程通信详解

Android中子线程和UI线程之间通信的详细解释 1.在多线程编程这块,我们经常要使用Handler,Thread和Runnable这三个类,那么他们之间的关系你是否弄清楚了呢?下面详解一下. 2.首先在开发Android应用时必须遵守单线程模型的原则: Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行. 3.Handler: (1).概念: Handler是沟通Activity 与Thread/runnable的桥梁.而Handler是运行在主UI线程中的,它与子线程

android主线程和子线程之间消息传递详解

从主线程发送消息到子线程(准确地说应该是非UI线程) package com.zhuozhuo; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.util.Log; import android.view.View; import android.

Android实现在子线程中更新Activity中UI的方法

本文实例讲述了Android实现在子线程中更新Activity中UI的方法.分享给大家供大家参考,具体如下: 在Android平台下,进行多线程编程时,经常需要在主线程之外的一个单独的线程中进行某些处理,然后更新用户界面显示.但是,在主线线程之外的线程中直接更新页面显示的问题是:系统会报这个异常: ERROR/AndroidRuntime(1222): android.view.ViewRoot$CalledFromWrongThreadException: Only the original

android使用handler ui线程和子线程通讯更新ui示例

复制代码 代码如下: package com.act262.sockettx; import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import and

android中UI主线程与子线程深入分析

本文较为深入的分析了android中UI主线程与子线程.分享给大家供大家参考.具体如下: 在一个Android 程序开始运行的时候,会单独启动一个Process.默认的情况下,所有这个程序中的Activity或者Service(Service和 Activity只是Android提供的Components中的两种,除此之外还有Content Provider和Broadcast Receiver)都会跑在这个Process. 一个Android 程序默认情况下也只有一个Process,但一个Pr

Android中Handler消息传递机制

Handler 是用来干什么的? 1)执行计划任务,可以在预定的时间执行某些任务,可以模拟定时器 2)线程间通信.在Android的应用启动时,会创建一个主线程,主线程会创建一个消息队列来处理各种消息.当你创建子线程时,你可以在你的子线程中拿到父线程中创建的Handler 对象,就可以通过该对象向父线程的消息队列发送消息了.由于Android要求在UI线程中更新界面,因此,可以通过该方法在其它线程中更新界面. 出于性能优化考虑,Android的UI操作并不是线程安全的,这意味着如果有多个线程并发

详解Android中Handler的内部实现原理

本文主要是对Handler和消息循环的实现原理进行源码分析,如果不熟悉Handler可以参见博文<详解Android中Handler的使用方法>,里面对Android为何以引入Handler机制以及如何使用Handler做了讲解. 概括来说,Handler是Android中引入的一种让开发者参与处理线程中消息循环的机制.我们在使用Handler的时候与Message打交道最多,Message是Hanlder机制向开发人员暴露出来的相关类,可以通过Message类完成大部分操作Handler的功

详解Android中Handler的使用方法

在Android开发中,我们经常会遇到这样一种情况:在UI界面上进行某项操作后要执行一段很耗时的代码,比如我们在界面上点击了一个"下载"按钮,那么我们需要执行网络请求,这是一个耗时操作,因为不知道什么时候才能完成.为了保证不影响UI线程,所以我们会创建一个新的线程去执行我们的耗时的代码.当我们的耗时操作完成时,我们需要更新UI界面以告知用户操作完成了.所以我们可能会写出如下的代码: package ispring.com.testhandler; import android.app.

Android中Handler与Message的简单实例

Android中Handler与Message的简单实例 前言: 虽然笔者已经学习了Android的AsyncTask来实现一部消息的处理.但是在android的学习中,经常会在一些demo中看到Handler与Message的一些使用,所以Handler与Message的学习也是有必要了.至于学多少,笔者还是比较坚持自己的看法,"用多少,学多少",毕竟已经有了AsyncTask如此方便的东西,Handler与Message也不是那么必不可缺了.(如此文的简单了解一下还是不需要花太多时

学习Android Handler消息传递机制

Android只允许UI线程修改Activity里的UI组件.当Android程序第一次启动时,Android会同时启动一条主线程(Main Thread),主线程主要负责处理与UI相关的事件,如用户的按键事件.屏幕绘图事件,并把相关的事件分发到对应的组件进行处理.所以,主线程通常又被称为UI线程. Android只允许UI线程修改Activity里的UI组件,这样会导致新启动的线程无法动态改变界面组件的属性值.但在实际的Android程序开发中,尤其是涉及动画的游戏开发中,需要让新启动的线程周

Android中handler使用浅析

1. Handler使用引出 现在作为客户,有这样一个需求,当打开Activity界面时,开始倒计时,倒计时结束后跳转新的界面(思维活跃的朋友可能立马想到如果打开后自动倒计时,就类似于各个APP的欢迎闪屏页面),如下图: 作为初学者,可能觉得直接开启一个包含倒序循环的子线程就ok了,具体实现如下: 1.1 Layout界面代码如下: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns

详解Android中Handler的实现原理

在 Android 中,只有主线程才能操作 UI,但是主线程不能进行耗时操作,否则会阻塞线程,产生 ANR 异常,所以常常把耗时操作放到其它子线程进行.如果在子线程中需要更新 UI,一般是通过 Handler 发送消息,主线程接受消息并且进行相应的逻辑处理.除了直接使用 Handler,还可以通过 View 的 post 方法以及 Activity 的 runOnUiThread 方法来更新 UI,它们内部也是利用了 Handler .在上一篇文章 Android AsyncTask源码分析 中

Android中Handler引起的内存泄露问题解决办法

在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用.通常我们的代码会这样实现. 复制代码 代码如下: public class SampleActivity extends Activity { private final Handler mLeakyHandler = new Handler() {     @Override     public void handleMessage(Message msg) {       // ...     }   }

Android 中Handler引起的内存泄露

在Android常用编程中,Handler在进行异步操作并处理返回结果时经常被使用.通常我们的代码会这样实现. public class SampleActivity extends Activity { private final Handler mLeakyHandler = new Handler() { @Override public void handleMessage(Message msg) { // ... } } } 但是,其实上面的代码可能导致内存泄露,当你使用Androi

详细介绍Android中回调函数机制

提示:在阅读本文章之前,请确保您对Touch事件的分发机制有一定的了解 在Android的学习过程中经常会听到或者见到"回调"这个词,那么什么是回调呢?所谓的回调函数就是:在A类中定义了一个方法,这个方法中用到了一个接口和该接口中的抽象方法,但是抽象方法没有具体的实现,需要B类去实现,B类实现该方法后,它本身不会去调用该方法,而是传递给A类,供A类去调用,这种机制就称为回调. 下面我们拿具体的Button的点击事件进行模拟分析: 首先,在View类中我们能找到setOnClickLis