Android为什么不能在子线程更新UI
Android为什么不能在子线程更新UI
- Android为什么不能在子线程更新UI?
- 如果不做这个校验,是不是我也可以正常在子线程更新UI
- 但是google为什么要这样去设计呢
- ViewRootImp是在onActivityCreated方法后面创建的吗
- 为什么一定需要checkThread呢
- 那为什么不加锁呢
- 为什么一开始在Activity的onCreate方法中创建一个子线程访问UI,程序还是正常能跑起来呢
- Android中子线程真的不能更新UI吗
- 保证上述条件1成立不就可以避免checkThread时候抛出异常了吗?为什么还需要开启消息循坏
- 使用子线程更新UI有实际应用场景吗
Android为什么不能在子线程更新UI?
// Android中为什么子线程不能更新UI?
viewRootImpl对象是在Activity中的onResume方法执行完成之后,View变得可见时才创建的,之前的操作是没有进行线程检查的,所以没有报错。但是ViewRootImpl创建之后,由于进行了checkThread操作,所以就不能在子线程更改UI了
当访问 UI 时,ViewRootImpl 会调用 checkThread方法去检查当前访问 UI 的线程是否为创建 UI 的那个线程,如果不是。则会抛出异常
如果不做这个校验,是不是我也可以正常在子线程更新UI
// 如果不做这个校验,是不是我也可以正常在子线程更新UI?
按理来说,这样是可以的
但是google为什么要这样去设计呢
// 但是google为什么要这样去设计呢
- 如果在不同的线程去控制用一个控件,由于网络延时或者大量耗时操作,会使UI绘制错乱,出了问题也很难去排查到底是哪个线程更新时出了问题;
- 主线程负责更新,子线程负责耗时操作,能够大大提高响应效率
- UI线程非安全线程,多线程进行并发访问有可能会导致内存溢出,降低硬件使用寿命;且非线程安全不能加Lock线程锁,否则会阻塞其他线程对View的访问,效率就会变得低下!
ViewRootImp是在onActivityCreated方法后面创建的吗
// ViewRootImp是在onActivityCreated方法后面创建的吗?
- ViewRootImpl是在Activity的onResume()方法后面创建出来的,所以在onResume之前的UI更新可以在子线程操作而不报错,因为这个时候ViewRootImpl还没有创建,没有执行checkThread()方法。
- 安卓系统中,操作viwe对象没有加锁,所以如果在子线程中更新UI,会出现多线程并发的问题,导致页面展示异常。
为什么一定需要checkThread呢
// 为什么一定需要checkThread呢?
因为UI控件不是线程安全的
那为什么不加锁呢
// 那为什么不加锁呢?
- 一是加锁会让UI访问变得复杂;
- 二是加锁会降低UI访问效率,会阻塞一些线程访问UI。
所以干脆使用单线程模型处理UI操作,使用时用Handler切换即可
为什么一开始在Activity的onCreate方法中创建一个子线程访问UI,程序还是正常能跑起来呢
// 为什么一开始在Activity的onCreate方法中创建一个子线程访问UI,程序还是正常能跑起来呢?
因为ViewRootImpl 的创建在 onResume 方法回调之后,而我们一开篇是在 onCreate 方法中创建了子线程并访问 UI,在那个时刻,ViewRootImpl 还没有创建,我们在因此 ViewRootImpl#checkThread 没有被调用到,也就是说,检测当前线程是否是创建的 UI 那个线程 的逻辑没有执行到,所以程序没有崩溃一样能跑起来。而之后修改了程序,让线程休眠了 3000 毫秒后,程序就崩了。很明显 3000 毫秒后 ViewRootImpl 已经创建了,可以执行 checkThread 方法检查当前线程
Android中子线程真的不能更新UI吗
// Android中子线程真的不能更新UI吗?
任何线程都可以更新自己创建的UI,但是需要满足各自对应的条件
- ViewRootImpl 还没创建出来之前。UI 修改的操作没有线程限制。因为 checkThread 方法不会被执行到。
- 在 ViewRootImpl 创建完成之后,保证「创建 ViewRootImpl 的操作」和「执行修改 UI 的操作」在同一个线程即可。也就是说,要在同一个线程调用 ViewManager的addView 和 ViewManager的updateViewLayout 方法。
// 注:ViewManager 是一个接口,WindowManger 接口继承了这个接口,我们通常都是通过 WindowManger(具体实现为 WindowMangerImpl) 进行 view 的 add remove update 操作的。
对应的线程需要创建 Looper 并且调用 Looper的loop 方法,开启消息循环。
保证上述条件1成立不就可以避免checkThread时候抛出异常了吗?为什么还需要开启消息循坏
// 保证上述条件1成立,不就可以避免checkThread时候抛出异常了吗?为什么还需要开启消息循坏?
条件 1 可以避免检查异常,但是无法保证 UI 可以被绘制出来。
条件 2 可以让更新的 UI 效果呈现出来。
注:WindowManger的addView 最终会调用WindowManageGlobal的addView方法,进而触发ViewRootImpl的setView 方法,该方法内部会调用ViewRootImpl的requestLayout 方法。根据 UI 绘制原理,下一步就是 scheduleTraversals了,该方法会往消息队列中插入一条消息屏障,然后调用 Choreographer的postCallback 方法,往 looper 中插入一条异步的 MSG_DO_SCHEDULE_CALLBACK 消息。等待垂直同步信号回来之后执行
使用子线程更新UI有实际应用场景吗
// 使用子线程更新 UI 有实际应用场景吗?
Android 中的 SurfaceView 通常会通过一个子线程来进行页面的刷新。如果我们的自定义 View 需要频繁刷新,或者刷新时数据处理量比较大,那么可以考虑使用 SurfaceView 来取代 View
Android为什么不能在子线程更新UI相关推荐
- Android子线程更新UI的方法总结
消息机制,对于Android开发者来说,应该是非常熟悉.对于处理有着大量交互的场景,采用消息机制,是再好不过了.有些特殊的场景,比如我们都知道,在Android开发中,子线程不能更新UI,而主线程又不 ...
- android 关于关于子线程更新UI的一些事
我们在看一些书或者博客时总是会看到一句话"android更新UI操作都是在Main主线程中,子线程中不能进行UI更新操作"那么,在子线程中真的不能进行UI的更新操作吗? //源码环 ...
- Android中Activity、Window、ViewRootImpl与子线程更新UI
三者层级关系 1.Window Window是一个抽象类,唯一的实现类是PhoneWindow Window分为三种类型应用Window.子Window.系统Window.子Window无法独立存在必 ...
- AndroidStudio子线程更新UI的几种方式
在安卓开发中,大部分情况下是不能在子线程直接更新UI的,只能在UI线程更新UI,其根本原因在于加入在一个Activity中有多个线程去更新UI,且没有加锁机制,可能会产生界面混乱的情况,但是如果都加锁 ...
- 面试官问我:Andriod为什么不能在子线程更新UI?
记得看文章三部曲,点赞,评论,转发. 微信搜索[程序员小安]关注还在移动开发领域苟活的大龄程序员,"面试系列"文章将在公众号同步发布. 1.前言 看完<你为什么在现在的公司不 ...
- C#利用Invoke和委托实现子线程更新UI(方式1)
UI布局如下 委托定义如下: public delegate void SetMessageDelegate(string message); From1的代码如下: public partial c ...
- pyqt5 子线程更新ui
from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * import time''' 信号 ...
- 子线程更新UI,牵扯activity的启动过程
http://m.blog.csdn.net/article/details?id=43449123 点击打开链接
- 为什么我的子线程更新了 UI 没报错?借此,纠正一些Android 程序员的一个知识误区...
开门见山: 这个误区是:子线程不能更新 UI ,其应该分类讨论,而不是绝对的. 半小时前,我的 XRecyclerView 群里面,一位群友私聊我,问题是: 为什么我的子线程更新了 UI 没报错? 我 ...
最新文章
- Stream Processing: Apache Kafka的Exactly-once的定义 原理和实现
- C++常用数据结构入门
- 计算机视觉:让冰冷的机器看懂多彩的世界
- 【MM模块】Material Planning - 物料计划
- 深入浅出设计模式原则之迪米特法则(LoD)
- 惠斯通电桥信号调理芯片_瑞萨推出集成LIN输出接口的传感器信号调理芯片,适用于电动/混动汽车HVAC系统...
- 查看照片的指定位置的像素点值,并在照片中绘制一条指定像素颜色的线段
- CAN和CANOpen的关系
- java线程池 的方法_JAVA线程池的实现方法
- Kafka : kafka errors.DisconnectException: null
- 12、图解横向扩容过程,如何超出扩容极限,以及如何提升容错性
- CMD 命令 文件操作
- 2020 智慧城市解决方案(智慧城市系统及相关技术)
- C语言实现一个关机程序
- 解决Worm.Win32.AutoRun.soq 病毒
- 【Java从零到架构师第③季】【30】SpringMVC-转发_重定向_路径问题总结
- 购物网站的商品推荐算法有哪些?
- Excel中如何快速输入☑和☒
- 宁夏召开外派教师家属新春慰问座谈会
- 基于Appfuse的Web应用快速开发
热门文章
- nginx域名访问的白名单配置梳理
- 无人机测绘技术在测绘领域的应用
- NetSuite 使用公司间跨组织履行处理销售和退货
- solrcloud 高可用集群搭建加solr整合hbase以及向ganglia报告度量
- 记:《洛克菲勒留给儿子的38封信》-- 37
- YOLO系列标注文件txt标签类别索引批量修改脚本
- keepass2android坚果云,Keepass+坚果云:多平台密码无缝同步(补)
- data fastboot 擦除_Fastboot 常用命令
- android手机系统怎么刷机包,安卓系统的手机如何刷机
- all elements are null问题