Android UI线程和非UI线程
Android UI线程和非UI线程
UI线程及Android的单线程模型原则
当应用启动,系统会创建一个主线程(main thread)。
这个主线程负责向UI组件分发事件(包括绘制事件),也是在这个主线程里,你的应用和Android的UI组件(components from the Android UI toolkit (components from the android.widget and android.view packages))发生交互。
所以main thread也叫UI thread也即UI线程。
系统不会为每个组件单独创建线程,在同一个进程里的UI组件都会在UI线程里实例化,系统对每一个组件的调用都从UI线程分发出去。
结果就是,响应系统回调的方法(比如响应用户动作的onKeyDown()和各种生命周期回调)永远都是在UI线程里运行。
当App做一些比较重(intensive)的工作的时候,除非你合理地实现,否则单线程模型的performance会很poor。
特别的是,如果所有的工作都在UI线程,做一些比较耗时的工作比如访问网络或者数据库查询,都会阻塞UI线程,导致事件停止分发(包括绘制事件)。对于用户来说,应用看起来像是卡住了,更坏的情况是,如果UI线程blocked的时间太长(大约超过5秒),用户就会看到ANR(application not responding)的对话框。
另外,Andoid UI toolkit并不是线程安全的,所以你不能从非UI线程来操纵UI组件。你必须把所有的UI操作放在UI线程里,所以Android的单线程模型有两条原则:
1.不要阻塞UI线程。
2.不要在UI线程之外访问Android UI toolkit(主要是这两个包中的组件:android.widget and android.view)。
使用Worker线程
根据单线程模型的两条原则,首先,要保证应用的响应性,不能阻塞UI线程,所以当你的操作不是即时的那种(not instantaneous),你应该把他们放进单另的线程中(叫做background或者叫worker线程)。
比如点击按钮后,下载一个图片然后在ImageView中展示:
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
Bitmap b = loadImageFromNetwork("http://example.com/image.png");
mImageView.setImageBitmap(b);
}
}).start();
}
这段代码用新的线程来处理网络操作,但是它违反了第二条原则:
Do not access the Android UI toolkit from outside the UI thread.
从非UI线程访问UI组件会导致未定义和不能预料的行为。
为了解决这个问题,Android提供了一些方法,从其他线程访问UI线程:
比如,上面这段代码可以这么改:
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(bitmap);
}
});
}
}).start();
}
这么改之后就是线程安全的了。
但是,当操作变得复杂的时候,这种代码会变得非常复杂,为了处理非UI线程和UI线程之间更加复杂的交互,可以考虑在worker线程中使用一个Handler,来处理UI线程中传来的消息。
也可以继承这个类AsyncTask 。
Communicating with the UI Thread
只有在UI线程中的对象才能操作UI线程中的对象,为了将非UI线程中的数据传送到UI线程,可以使用一个 Handler运行在UI线程中。
Handler是Android framework中管理线程的部分,一个Handler对象负责接收消息然后处理消息。
你可以为一个新的线程创建一个Handler,也可以创建一个Handler然后将它和已有线程连接。
如果你将一个Handler和你的UI线程连接,处理消息的代码就将会在UI线程中执行。
可以在你创建线程池的类的构造方法中实例化Handler的对象,然后用全局变量存储这个对象。
要和UI线程连接,实例化Handler的时候应该使用Handler(Looper) 这个构造方法。
这个构造方法使用了一个 Looper 对象,这是Android系统中线程管理的framework的另一个部分。
当你用一个特定的 Looper实例来创建一个 Handler时,这个 Handler就运行在这个 Looper的线程中。
在Handler中,要覆写handleMessage() 方法。Android系统会在Handler管理的相应线程收到新消息时调用这个方法。
一个特定线程的所有Handler对象都会收到同样的方法。(这是一个“一对多”的关系)。
参考资料
官方Training: 与UI线程通信:
http://developer.android.com/training/multiple-threads/communicate-ui.html
Guides: Processes and Threads
http://developer.android.com/guide/components/processes-and-threads.html
类参考:
http://developer.android.com/reference/android/os/Looper.html
http://developer.android.com/reference/android/os/Handler.html
http://developer.android.com/reference/android/os/HandlerThread.html
博客:
Android的线程使用来更新UI----Thread、Handler、Looper、TimerTask等:
http://www.cnblogs.com/playing/archive/2011/03/24/1993583.html
Android UI线程和非UI线程的更多相关文章
- android脚步---如何看log之程序停止运行,和UI线程和非UI线程之间切换
经常运行eclipse时,烧到手机出现,“停止运行”,这时候得通过logcat查log了.一般这种情况属于FATAL EXCEPTION,所以检索FATAL 或者 EXCEPTION,然后往下看几行 ...
- 关于 SWT 的UI线程和非UI线程
要理解UI线程,先要了解一下“消息循环”这个概念.链接是百度百科上的条目,简单地说,操作系统把用户界面上的每个操作都转化成为对应的消息,加入消息队列.然后把消息转发给对应的应用程序(一般来说,就是活动 ...
- Java中的守护线程和非守护线程(转载)
<什么是守护线程,什么是非守护线程> Java有两种Thread:"守护线程Daemon"(守护线程)与"用户线程User"(非守护线程). 用户线 ...
- 从头认识java-18.2 主要的线程机制(5)-守护线程与非守护线程
这一章节我们来讨论一下守护线程与非守护线程. 1.什么是守护线程?什么是非守护线程? 非守护线程:Java虚拟机在它全部非守护线程已经离开后自己主动离开. 守护线程:守护线程则是用来服务用户线程的,假 ...
- Android线程---UI线程和非UI线程之间通信
近期自学到了线程这一块,用了一上午的时间终于搞出来了主.子线程间的相互通信.当主线程sendMessage后,子线程便会调用handleMessage来获取你所发送的Message.我的主线程 ...
- Android开之在非UI线程中更新UI
当在非UI线程中更新UI(程序界面)时会出现例如以下图所看到的的异常: 那怎样才干在非UI线程中更细UI呢? 方法有非常多种.在这里主要介绍三种: 第一种:调用主线程mHandler的post(Run ...
- java多线程之守护线程与非守护线程
在java线程中有两种线程,一种是用户线程,其余一种是守护线程. 守护线程具有特殊的含义,比如gc线程.当最后一个非守护线程执行完后,守护线程随着jvm一同结束工作. java中的守护线程需要将Dae ...
- java的守护线程与非守护线程
最近重新研究Java基础知识,发现以前太多知识知识略略带过了,比较说Java的线程机制,在Java中有两类线程:User Thread(用户线程).Daemon Thread(守护线程) ,(PS:以 ...
- [Java基础] java的守护线程与非守护线程
最近重新研究Java基础知识,发现以前太多知识知识略略带过了,比较说Java的线程机制,在Java中有两类线程:User Thread(用户线程).Daemon Thread(守护线程) ,(PS:以 ...
随机推荐
- JS网页顶部弹出可关闭广告图层
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Azure ARM (5) ARM Template初探 - 本地JSON Template文件(1)
<Windows Azure Platform 系列文章目录> Azure ARM (1) 概览 Azure ARM (2) 概览 Azure ARM (3) ...
- [New Portal]Windows Azure Cloud Service (34) TechEd 2013 North America关于Azure的最新消息
<Windows Azure Platform 系列文章目录> 话说TechEd 2013 US上个月3-6日在美国举办了,笔者的文章又有点姗姗来迟了. 需要了解相关视频的网友,请浏览ht ...
- 23套新鲜出炉的网站和手机界面 PSD 素材
Web 用户界面,移动用户界面和线框套件对设计师很有用,因为这些套件让他们使用快速和有效的方式复制用户界面.这些类型的工具包提供了一个基本的用户界面元素,用于它们需要制作的网站或软件模型. 在这篇文章 ...
- Git学习笔记(四)
一.忽略特殊文件 在Git工作区的根目录下创建一个特殊的.gitignore文件,然后把要忽略的文件名填进去,Git就会自动忽略这些文件. 不需要从头写.gitignore文件,GitHub已经为我们 ...
- Html5离线缓存详细讲解
离线缓存是Html5新特性之一,简单理解就是第一次加载后将数据缓存,在没有清除缓存前提下,下一次没有网络也可以加载,用在静态数据的网页或游戏比较好用.当然,Html5新的特性都不是所有浏览器都能支持的 ...
- ADO.NET封装的SqlHelper
参照别人的方法,顺便再次复习下ADO.NET的相关知识.为自己的类库做准备. namespace Common.SqlHelper { /// <summary> /// ADO.NET- ...
- 【原创】kafka controller源代码分析(一)
Kafka集群中的一个broker会被作为controller负责管理分区和副本的状态以及执行类似于重分配分区之类的管理任务.如果当前的controller失败了,会从剩下的broker中选出新的co ...
- 【C#】注意用“划算”的方式使用图标
先解释一下何谓“划算”:假定一个Winform程序包含若干个窗体,每个窗体左上角都要显示图标(即要设置Form.Icon属性),该程序本身也要有个图标(用于在OS资源管理器中显示),所有这些图标都是一 ...
- 传智播客JavaWeb听课总结
一. JavaWeb基础 第一天: 1.Eclipse详解: (1).Bad versionnumber in .class file:编译器版本和运行(JRE)版本不符合.高的JRE版本兼容低版本的 ...