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线程:
- Activity.runOnUiThread(Runnable)
- View.post(Runnable)
- View.postDelayed(Runnable, long)
比如,上面这段代码可以这么改:
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
转载于:https://www.cnblogs.com/Cyning/p/3650990.html
Android UI线程和非UI线程相关推荐
- android 组件 线程,Android UI线程和非UI线程
UI线程及Android的单线程模型原则 当应用启动,系统会创建一个主线程(main thread). 这个主线程负责向UI组件分发事件(包括绘制事件),也是在这个主线程里,你的应用和Android的 ...
- Android开发之UI线程和非UI线程
这里又是老生畅谈的话了,前边已经有多篇文章针对线程进行探究解释,Android开发过程中线程的体现更是淋漓尽致.Android开发过程中涉及到的线程从大类上分可以归为两类:UI线程和非UI线程.本篇就 ...
- SWT的UI线程和非UI线程
为什么80%的码农都做不了架构师?>>> 要理解UI线程,先要了解一下"消息循环"这个概念.链接是百度百科上的条目,简单地说,操作系统把用户界面上的每个操作 ...
- 守护线程与非守护线程的区别
守护线程与非守护线程 最近在看多线程的Timer章节,发现运用到了守护线程,感觉Java的基础知识还是需要补充. Java分为两种线程:用户线程和守护线程 所谓守护线程是指在程序运行的时候在后台提供一 ...
- Java中的守护线程和非守护线程(转载)
<什么是守护线程,什么是非守护线程> Java有两种Thread:"守护线程Daemon"(守护线程)与"用户线程User"(非守护线程). 用户线 ...
- 守护线程和非守护线程
直觉上来讲,守护线程和main相关 Java中有两种线程,一种是用户线程,另一种是守护线程. 用户线程是指用户自定义创建的线程,主线程停止,用户线程不会停止(另一条执行路径) 守护线程当进程不存在或主 ...
- 多线程基础-守护线程与非守护线程
守护线程与非守护线程 1.线程分类: 2.程序线程: 3.主线程与非守护线程 4.主线程与守护线程 5.主线程.守护线程.非守护线程 6. java虚拟机是如何退出的? 1.线程分类: 守护线程 非守 ...
- java守护线程与非守护线程
java守护线程与非守护线程 代码逻辑 当前网上结论 1.主线程结束,守护线程跟着结束 2.只要存在任何一个非守护线程,守护线程就全部工作 测试代码 第一段代码 第二段代码 结论 代码逻辑 代码里面包 ...
- 守护线程是什么?守护线程和非守护线程的区别是?守护线程的作用是?
守护线程是区别于用户线程,用户线程即我们手动创建的线程,而守护线程是程序运行的时候在后台提供一种通用服务的线程.垃圾回收线程就是典型的守护线程. 守护线程和非守护线程的区别是 public stati ...
最新文章
- CSDN蒋涛提出技术社区三倍速定律,称下一个20年全球开发者数量将过亿
- 排序算法学习——冒泡排序
- 铁路 12306 网站否认发生用户信息泄漏
- 七十六、Python | Leetcode二分查找和分治算法系列
- Vue010_ 过滤器
- python文件图标变成小电脑_手把手教你给Python程序写图形界面,并且打包成exe文件-exe文件...
- linux知识(二)互斥量、信号量和生产者消费者模型
- python listdir报错_Python常见十六个错误集合,你知道那些?
- cpu线程_CPU核数和线程数有什么用?什么意思?CPU核数和线程的关系与区别
- java mysql 主键生成策略_主键生成策略
- C++算法学习(力扣:201. 数字范围按位与)
- 达摩达兰论估价pdf_故事与估值epub+azw3+mobi文字版pdf+txt多看word魔鸠搜雅书屋
- mount –o remount,rw /
- RGB565颜色表,附RGB888转RGB565工具,RGB24转RGB565工具
- 哈佛《幸福课》 第2课 为什么要学积极心理学
- MATLAB工具学习:cftool(曲线拟合工具)
- 楷体描红字帖练起来@简洁字帖
- 2021年终总结:平凡的一年
- ruoyi-cloud 服务器端idea启动报错Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.6.0:exec (defau
- Java程序猿必学第十一篇——接口
热门文章
- 【Spring Boot】【Thymeleaf】The SpringStandard Dialect
- Spring RMI错误:java.rmi.ConnectException: Connection refused to host: 127.0.0.1
- 编译 PHP7.0为什么那么慢,CentOS 7编译安装php7.0.7以及可能遇到的问题的解决方案...
- html代码常用软件,HTML代码实际应用讲解
- php 5w的并发需要多少台服务器_php使用异步编程是怎样的?
- 小学计算机说课稿,小学信息技术说课稿《新建文件夹》
- 触发bfc的html元素,什么是BFC? CSS 使用伪元素清除浮动的方法
- MATLAB调试caffe,在MATLAB下调试Caffe
- c3p0 高并发mysql 连接sleep情况
- VMware Fusion 静态ip