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线程相关推荐

  1. android 组件 线程,Android UI线程和非UI线程

    UI线程及Android的单线程模型原则 当应用启动,系统会创建一个主线程(main thread). 这个主线程负责向UI组件分发事件(包括绘制事件),也是在这个主线程里,你的应用和Android的 ...

  2. Android开发之UI线程和非UI线程

    这里又是老生畅谈的话了,前边已经有多篇文章针对线程进行探究解释,Android开发过程中线程的体现更是淋漓尽致.Android开发过程中涉及到的线程从大类上分可以归为两类:UI线程和非UI线程.本篇就 ...

  3. SWT的UI线程和非UI线程

    为什么80%的码农都做不了架构师?>>>    要理解UI线程,先要了解一下"消息循环"这个概念.链接是百度百科上的条目,简单地说,操作系统把用户界面上的每个操作 ...

  4. 守护线程与非守护线程的区别

    守护线程与非守护线程 最近在看多线程的Timer章节,发现运用到了守护线程,感觉Java的基础知识还是需要补充. Java分为两种线程:用户线程和守护线程 所谓守护线程是指在程序运行的时候在后台提供一 ...

  5. Java中的守护线程和非守护线程(转载)

    <什么是守护线程,什么是非守护线程> Java有两种Thread:"守护线程Daemon"(守护线程)与"用户线程User"(非守护线程). 用户线 ...

  6. 守护线程和非守护线程

    直觉上来讲,守护线程和main相关 Java中有两种线程,一种是用户线程,另一种是守护线程. 用户线程是指用户自定义创建的线程,主线程停止,用户线程不会停止(另一条执行路径) 守护线程当进程不存在或主 ...

  7. 多线程基础-守护线程与非守护线程

    守护线程与非守护线程 1.线程分类: 2.程序线程: 3.主线程与非守护线程 4.主线程与守护线程 5.主线程.守护线程.非守护线程 6. java虚拟机是如何退出的? 1.线程分类: 守护线程 非守 ...

  8. java守护线程与非守护线程

    java守护线程与非守护线程 代码逻辑 当前网上结论 1.主线程结束,守护线程跟着结束 2.只要存在任何一个非守护线程,守护线程就全部工作 测试代码 第一段代码 第二段代码 结论 代码逻辑 代码里面包 ...

  9. 守护线程是什么?守护线程和非守护线程的区别是?守护线程的作用是?

    守护线程是区别于用户线程,用户线程即我们手动创建的线程,而守护线程是程序运行的时候在后台提供一种通用服务的线程.垃圾回收线程就是典型的守护线程. 守护线程和非守护线程的区别是 public stati ...

最新文章

  1. CSDN蒋涛提出技术社区三倍速定律,称下一个20年全球开发者数量将过亿
  2. 排序算法学习——冒泡排序
  3. 铁路 12306 网站否认发生用户信息泄漏
  4. 七十六、Python | Leetcode二分查找和分治算法系列
  5. Vue010_ 过滤器
  6. python文件图标变成小电脑_手把手教你给Python程序写图形界面,并且打包成exe文件-exe文件...
  7. linux知识(二)互斥量、信号量和生产者消费者模型
  8. python listdir报错_Python常见十六个错误集合,你知道那些?
  9. cpu线程_CPU核数和线程数有什么用?什么意思?CPU核数和线程的关系与区别
  10. java mysql 主键生成策略_主键生成策略
  11. C++算法学习(力扣:201. 数字范围按位与)
  12. 达摩达兰论估价pdf_故事与估值epub+azw3+mobi文字版pdf+txt多看word魔鸠搜雅书屋
  13. mount –o remount,rw /
  14. RGB565颜色表,附RGB888转RGB565工具,RGB24转RGB565工具
  15. 哈佛《幸福课》 第2课 为什么要学积极心理学
  16. MATLAB工具学习:cftool(曲线拟合工具)
  17. 楷体描红字帖练起来@简洁字帖
  18. 2021年终总结:平凡的一年
  19. ruoyi-cloud 服务器端idea启动报错Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.6.0:exec (defau
  20. Java程序猿必学第十一篇——接口

热门文章

  1. 【Spring Boot】【Thymeleaf】The SpringStandard Dialect
  2. Spring RMI错误:java.rmi.ConnectException: Connection refused to host: 127.0.0.1
  3. 编译 PHP7.0为什么那么慢,CentOS 7编译安装php7.0.7以及可能遇到的问题的解决方案...
  4. html代码常用软件,HTML代码实际应用讲解
  5. php 5w的并发需要多少台服务器_php使用异步编程是怎样的?
  6. 小学计算机说课稿,小学信息技术说课稿《新建文件夹》
  7. 触发bfc的html元素,什么是BFC? CSS 使用伪元素清除浮动的方法
  8. MATLAB调试caffe,在MATLAB下调试Caffe
  9. c3p0 高并发mysql 连接sleep情况
  10. VMware Fusion 静态ip