由UI刷新谈到线程安全和Android单线程模型
1、为什么说invalidate()不能直接在线程中调用?
Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在非UI主线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。例如:在非UI线程中调用invalidate会导致线程不安全,也就是说可能在非UI线程中刷新界面的时候,UI线程(或者其他非UI线程)也在刷新界面,这样就导致多个界面刷新的操作不能同步,导致线程不安全
2、它是怎么违背单线程的?
一个 Android 程序开始运行时,就有一个主线程Main Thread被创建。该线程主要负责UI界面的显示、更新和控件交互,所以又叫UI Thread。由于只有UI线程更新界面所以说Android是单线程模型。
一个Android程序创建之初,一个Process呈现的是单线程模型--即Main Thread,在非主线程(UI线程)外调invalidate()刷新界面出现异常,即是说用其他的线程更新UI,android中是不被允许的。
3、android ui为什么说不是线程安全的?
UI线程存在不安全的操作:android UI 中提供invalidate()来更新界面,而invalidate()方法是线程不安全。
4、android ui操作为什么一定要在UI线程中执行?
UI主线程是更新UI界面的,更新了界面才能看到运行的效果。
再者Android UI操作并不是线程安全的并且这些操作必须在UI线程中执行。如果在子线程中直接修改UI,会导致异常。
5、UI线程及Android的单线程模型原则
5.1 main thread
当应用启动,系统会创建一个主线程(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线程。
5.2 UI thread
系统不会为每个组件单独创建线程,在同一个进程里的UI组件都会在UI线程里实例化,系统对每一个组件的调用都从UI线程分发出去。
结果就是,响应系统回调的方法(比如响应用户动作的onKeyDown()和各种生命周期回调)永远都是在UI线程里运行。
5.3 耗时任务
当App做一些比较重(intensive)的工作的时候,除非你合理地实现,否则单线程模型的performance会很poor。
特别的是,如果所有的工作都在UI线程,做一些比较耗时的工作比如访问网络或者数据库查询,都会阻塞UI线程,导致事件停止分发(包括绘制事件)。对于用户来说,应用看起来像是卡住了,更坏的情况是,如果UI线程blocked的时间太长(大约超过5秒),用户就会看到ANR(application not responding)的对话框。
5.4 Android单线程模型两原则
另外,Andoid UI toolkit并不是线程安全的,所以你不能从非UI线程来操纵UI组件。你必须把所有的UI操作放在UI线程里,所以Android的单线程模型有两条原则:
1.不要阻塞UI线程。
2.不要在UI线程之外访问Android UI toolkit(主要是这两个包中的组件:android.widget and android.view)。
5.5 由一个例子展开线程间通信问题http://blog.csdn.net/lvxiangan/article/details/39504145
6、invalidate()/postInvalidate()
Android程序中可以使用的界面刷新方法有两种,分别是利用invalidate和利用postInvalidate()来实现在线程中刷新界面。
Android中实现view的更新有两组方法,一组是invalidate,另一组是postInvalidate,其中前者是在UI线程自身中使用,而后者在非UI线程中使用。
Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。
6.1 特点
只要是view的子类,都会从view中继承invalidate和postInvalidate这两个方法。
当invalidate方法被调用的时候,就是在告诉系统,当前的view发生改变,应该尽可能快的来进行重绘。
这个方法仅能在UI线程中被调用。如果想要在工作线程中进行刷新界面,那么其他的方法将会被调用,这个方法就是postInvalidate方法。这个方法将会发送消息到主线程,当主线程的消息队列轮询到当前消息的时候,这个方法会被调用。
但是需要注意的是,刷新界面并不能保证马上刷新。只是尽可能快的进行刷新。尤其是在postInvalidate方法中,这种情况会出现。
7、小结
- 界面刷新的存在:UI界面要看想到运行效果,必定存在界面刷新这一需求
- UI线程不安全:要刷新就得调用invalidate(),所以UI线程是线程不安全的
- 界面刷新的运行:谈到刷新,就得明确这一动作只能在UI线程进行,多线程各自刷新是不可想象的
- 单线程模型:由3可得Android是单线程模型这一观点,相应的也就存在着Android单线程模型两原则
- postInvalidate():postInvalidate()只是将刷新消息发送到主线程,至于是否刷新、何时刷新得看主线程的运行
http://www.android100.org/html/201406/06/20132.html
由UI刷新谈到线程安全和Android单线程模型的更多相关文章
- 为什么说android UI操作不是线程安全的
转载于:http://blog.csdn.net/lvxiangan/article/details/17218409#t2 UI线程及Android的单线程模型原则 使用Worker线程 Commu ...
- Android开发 View的UI刷新Invalidate和postInvalidate
Invalidate 正常刷新 /** * 使整个视图无效.如果视图可见, * {@link #onDraw(android.graphics.Canvas)} 调用此方法后将在后续的UI刷新里调用o ...
- Android的UI设计与后台线程交互
本文将讨论Android应用程序的线程模型以及如何使用线程来处理耗时较长的操作,而不是在主线程中执行,保证用户界面(UI)的流畅运行.本文还将阐述一些用户界面(UI)中与线程交互的API.UI用户界面 ...
- Android开发UI之在子线程中更新UI
转自第一行代码-Android Android是不允许在子线程中进行UI操作的.在子线程中去执行耗时操作,然后根据任务的执行结果来更新相应的UI控件,需要用到Android提供的异步消息处理机制. 代 ...
- 转载【浅谈ThreadPool 线程池】
浅谈ThreadPool 线程池 http://www.cnblogs.com/xugang/archive/2010/04/20/1716042.html
- 浅谈Java线程安全
浅谈Java线程安全 - - 2019-04-25 17:37:28 线程安全 Java中的线程安全 按照线程安全的安全程序由强至弱来排序,我们可以将Java语言中各种操作共享的数据分为以下五类 ...
- 浅谈ThreadPool 线程池(引用)
出自:http://www.cnblogs.com/xugang/archive/2010/04/20/1716042.html 浅谈ThreadPool 线程池 相关概念: 线程池可以看做容纳线程的 ...
- 【转】浅谈Node.js单线程模型
Node.js采用 事件驱动 和 异步I/O 的方式,实现了一个单线程.高并发的运行时环境,而单线程就意味着同一时间只能做一件事,那么Node.js如何利用单线程来实现高并发和异步I/O?本文将围绕这 ...
- UI开发模式对比:JSP、Android、Flex
前一篇文章分析了Java平台下不同类型WEB框架对开发模式的影响,多数Java领域的WEB框架都是聚焦于服务端MVC的实现,这些框架对View的支持,通常是基于标准的JSP或类似JSP的模板技术如Fr ...
随机推荐
- (博弈 sg入门2)
接下来介绍Nim游戏(同样引用杭电上的,懒的打字) 1.有两个玩家: 2. 有三堆扑克牌(比如:可以分别是 5,7,9张): 3. 游戏双方轮流操作: 4. 玩家的每次操作是选择其中某 ...
- Rhino 使 JavaScript 应用程序更灵动(转载)
脚本语言有良好的快速开发,高效率的执行,解释而非编译执行等优点,并且具有与其他语言编写的组件之间强大的通信功能.JavaScript 一直是脚本语言中的领头羊,它是一门具有非常丰富特性的语言.除了浏览 ...
- 如何把asp.net上的服务在iis调试
1,在iis上部署一个应用,路径指向工程目录 2,在vs2012(其他版本没试过,10都很久没用不记得了)中打开网站,选择本地iis 3,在你想调试的地方设置断点,F5,搞定!
- 洛谷P4556 [Vani有约会]雨天的尾巴(线段树合并)
题目背景 深绘里一直很讨厌雨天. 灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切. 虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地 ...
- OpenSSL命令---CRL
用途: crl工具,用于处里PME或DER格式的CRL文件. 用法: openssl crl [-inform PEM|DER] [-outform PEM|DER] [-text] [-in fil ...
- 并发处理 - 配置文件"并发:报表访问层"的设置 (Doc ID 1625757.1)
文档内容 目标 解决方案 适用于: Oracle Concurrent Processing - 版本 12.0.0 到 12.2 [发行版 12 到 12.2] 本文档所含信息适用于所有平台 ...
- 后台web请求代码(含https,json提交)
后台web请求 namespace XXXX.Utilites { using System; using System.Collections.Generic; using System.IO; u ...
- VS2017新建控制器出现 No executable found matching command: dotnet-asp net-code generator解决办法
编辑项目.csproj的文件,里面加上如下节点保存即可: <ItemGroup> <DotNetCliToolReference Include="Microsof ...
- Git命令行学习积累
1.远程分支拉取到本地 $ git checkout -b develop origin/develop //检出远程的develop分支到本地 2.本地分支推送到远程 $ git checkout ...
- Js 事件详解
1.事件流 1.1 事件流 描述的是在页面中接受事件的顺序 1.2 事件冒泡 由最具体的元素接收,然后逐级向上传播最不具体的元素的节点(文档) 1.3 事件捕获 最不具体的节点先接收事件,而最具体的节 ...