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.view)。

使用Worker线程

根据单线程模型的两条原则,首先,要保证应用的响应性,不能阻塞UI线程,所以当你的操作不是即时的那种(not instantaneous),你应该把他们放进单另的线程中(叫做background或者叫worker线程)。

比如点击按钮后,下载一个图片然后在ImageView中展示:

publicvoidonClick(View v) {

newThread(newRunnable() {

publicvoidrun() {

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线程:

比如,上面这段代码可以这么改:

publicvoidonClick(View v) {

newThread(newRunnable() {

publicvoidrun() {

finalBitmap bitmap = loadImageFromNetwork("http://example.com/image.png");

mImageView.post(newRunnable() {

publicvoidrun() {

mImageView.setImageBitmap(bitmap);

}

});

}

}).start();

}

这么改之后就是线程安全的了。

但是,当操作变得复杂的时候,这种代码会变得非常复杂,为了处理非UI线程和UI线程之间更加复杂的交互,可以考虑在worker线程中使用一个

也可以继承这个类AsyncTask 。

与UI线程通信

只有在UI线程中的对象才能操作UI线程中的对象,为了将非UI线程中的数据传送到UI线程,可以使用一个 Handler运行在UI线程中。

Handler是Android framework中管理线程的部分,一个Handler对象负责接收消息然后处理消息。

你可以为一个新的线程创建一个Handler,也可以创建一个Handler然后将它和已有线程连接。

如果你将一个Handler和你的UI线程连接,处理消息的代码就将会在UI线程中执行。

可以在你创建线程池的类的构造方法中实例化Handler的对象,然后用全局变量存储这个对象。

要和UI线程连接,实例化Handler的时候应该使用

这个构造方法使用了一个

当你用一个特定的 Looper实例来创建一个 Handler时,这个 Handler就运行在这个Looper的线程中。

在Handler中,要覆写会在Handler管理的相应线程收到新消息时调用这个方法。

一个特定线程的所有Handler对象都会收到同样的方法。(这是一个“一对多”的关系)。

参考资料

官方Training: 与UI线程通信:

Guides: Processes and Threads

类参考:

【移动开发视频课程推荐】

【责任编辑:徐川 TEL:(010)68476606】

点赞 0

android 组件 线程,Android UI线程和非UI线程相关推荐

  1. android 组件可见,android界面控件可见性方法setVisibility()3个可选参数(visible,invisible,gone)的区别...

    setVisibility()有三个参数:visible, invisible,gone 1. visible :设置为可见 2. invisible : 设置为不可见,但是保留它在父控件上所占的空间 ...

  2. android组件设计,Android组件化开发路由的设计实践

    调研了一下目前的路由框架,ARouter(阿里的),ActivityRouter都使用了apt技术 编译时注解,个人想法是一口吃不成胖子,先做个比较实用的. VpRouter路由框架主要应用于组件化开 ...

  3. android组件权限,Android中Permission权限机制的具体使用

    由上篇Android Permission权限机制引子,我们知道Android 通过在每台设备上实施了基于权限的安全策略来处理安全问题,采用权限来限制安装应用程序的能力.本篇文章继续来探讨和Andro ...

  4. android 组件大小,Android编程获取组件尺寸大小的方法

    本文实例讲述了Android编程获取组件尺寸大小的方法.分享给大家供大家参考,具体如下: 在oncreate()中利用view.getWidth()或是view.getHeiht()来获取view的宽 ...

  5. android组件圆角,Android实现圆角控件

    Android实现圆角控件 在Android开发过程中,控件的使用是最常见.最基本的.但是我们都知道,在Android中的控件都是矩形的,而在实际项目中,我们的UI设计师经常会使用一些圆角的控件.那么 ...

  6. android组件启动,Android四大组件Service之StartService启动

    对于Service两种方式在概述里已经介绍了,下面是学习是StartService的代码实例. service启动代码: package com.example.service01; import a ...

  7. android 组件 excel,Android中利用jxl组件来操作excel

    1.支持Excel 95-2000的所有版本,生成Excel 2000标准格式,支持字体.数字.日期操作,能够修饰单元格属性,支持图像和图表, 最关键的是这套API是纯Java的,并不依赖Window ...

  8. android c++ 线程,Android多线程分析之二:Thread的实现

    Android多线程分析之二:Thread的实现在前文<Android多线程分析之一:使用Thread异步下载图像>中演示了如何使用 Thread 处理异步事务.示例中这个 Java Th ...

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

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

最新文章

  1. #2002-The server is not responding (or the local MySQL server's socket is not correctly configur
  2. UEFI + GPT 启动 VHD
  3. spriteatlas 白屏的问题_Discuz白屏问题解决思
  4. 银行考试计算机重点知识,银行计算机考试试题
  5. 也玩ASP.NET MVC 与 WebFroms 整合
  6. 京东商城架构峰值系统设计
  7. Unity之FBX文件操作学习笔记(一)
  8. 几种ESB(企业服务总线)介绍
  9. js直接打开word文件
  10. 惊喜来袭~进阶版《看漫画学Python 2:有趣、有料、好玩、好用》
  11. [ERROR] Error executing Maven.
  12. Flink 1.11 中的动态加载 udf jar 包
  13. 早期系统虚拟机分享 windows虚拟机vmdk
  14. Matplotlib之条形图绘制
  15. openwrt mesh网络设置
  16. 最快Android模拟器Genymotion的安装与使用完整教程(多图,慎点)
  17. 环境变量setenv函数和export命令的解释
  18. mysql内存参数及最大内存
  19. Linux系统命令与网络、磁盘参数和日志监控
  20. 【Makefile】strip

热门文章

  1. 给element-ui的steps加点击事件
  2. 绕过TracerPid检测
  3. 仿Mathematica中的函数ProductLog
  4. 2020-11-4(安卓开发)
  5. pwn学习总结(一) —— 常用命令
  6. 正则表达式 perl
  7. 6、MySQL慢查询日志(Slow Query Log)
  8. 【PAT乙级】1081 检查密码 (15 分)
  9. 【PAT乙级】1047 编程团体赛 (20 分)
  10. 【PAT乙级】1028 人口普查 (20 分)