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为什么要这样去设计呢

  1. 如果在不同的线程去控制用一个控件,由于网络延时或者大量耗时操作,会使UI绘制错乱,出了问题也很难去排查到底是哪个线程更新时出了问题;
  2. 主线程负责更新,子线程负责耗时操作,能够大大提高响应效率
  3. UI线程非安全线程,多线程进行并发访问有可能会导致内存溢出,降低硬件使用寿命;且非线程安全不能加Lock线程锁,否则会阻塞其他线程对View的访问,效率就会变得低下!

ViewRootImp是在onActivityCreated方法后面创建的吗

// ViewRootImp是在onActivityCreated方法后面创建的吗?

  1. ViewRootImpl是在Activity的onResume()方法后面创建出来的,所以在onResume之前的UI更新可以在子线程操作而不报错,因为这个时候ViewRootImpl还没有创建,没有执行checkThread()方法。
  2. 安卓系统中,操作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,但是需要满足各自对应的条件

  1. ViewRootImpl 还没创建出来之前。UI 修改的操作没有线程限制。因为 checkThread 方法不会被执行到。
  2. 在 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相关推荐

  1. Android子线程更新UI的方法总结

    消息机制,对于Android开发者来说,应该是非常熟悉.对于处理有着大量交互的场景,采用消息机制,是再好不过了.有些特殊的场景,比如我们都知道,在Android开发中,子线程不能更新UI,而主线程又不 ...

  2. android 关于关于子线程更新UI的一些事

    我们在看一些书或者博客时总是会看到一句话"android更新UI操作都是在Main主线程中,子线程中不能进行UI更新操作"那么,在子线程中真的不能进行UI的更新操作吗? //源码环 ...

  3. Android中Activity、Window、ViewRootImpl与子线程更新UI

    三者层级关系 1.Window Window是一个抽象类,唯一的实现类是PhoneWindow Window分为三种类型应用Window.子Window.系统Window.子Window无法独立存在必 ...

  4. AndroidStudio子线程更新UI的几种方式

    在安卓开发中,大部分情况下是不能在子线程直接更新UI的,只能在UI线程更新UI,其根本原因在于加入在一个Activity中有多个线程去更新UI,且没有加锁机制,可能会产生界面混乱的情况,但是如果都加锁 ...

  5. 面试官问我:Andriod为什么不能在子线程更新UI?

    记得看文章三部曲,点赞,评论,转发. 微信搜索[程序员小安]关注还在移动开发领域苟活的大龄程序员,"面试系列"文章将在公众号同步发布. 1.前言 看完<你为什么在现在的公司不 ...

  6. C#利用Invoke和委托实现子线程更新UI(方式1)

    UI布局如下 委托定义如下: public delegate void SetMessageDelegate(string message); From1的代码如下: public partial c ...

  7. pyqt5 子线程更新ui

    from PyQt5.QtCore import * from PyQt5.QtGui import * from PyQt5.QtWidgets import * import time''' 信号 ...

  8. 子线程更新UI,牵扯activity的启动过程

    http://m.blog.csdn.net/article/details?id=43449123 点击打开链接

  9. 为什么我的子线程更新了 UI 没报错?借此,纠正一些Android 程序员的一个知识误区...

    开门见山: 这个误区是:子线程不能更新 UI ,其应该分类讨论,而不是绝对的. 半小时前,我的 XRecyclerView 群里面,一位群友私聊我,问题是: 为什么我的子线程更新了 UI 没报错? 我 ...

最新文章

  1. Stream Processing: Apache Kafka的Exactly-once的定义 原理和实现
  2. C++常用数据结构入门
  3. 计算机视觉:让冰冷的机器看懂多彩的世界
  4. 【MM模块】Material Planning - 物料计划
  5. 深入浅出设计模式原则之迪米特法则(LoD)
  6. 惠斯通电桥信号调理芯片_瑞萨推出集成LIN输出接口的传感器信号调理芯片,适用于电动/混动汽车HVAC系统...
  7. 查看照片的指定位置的像素点值,并在照片中绘制一条指定像素颜色的线段
  8. CAN和CANOpen的关系
  9. java线程池 的方法_JAVA线程池的实现方法
  10. Kafka : kafka errors.DisconnectException: null
  11. 12、图解横向扩容过程,如何超出扩容极限,以及如何提升容错性
  12. CMD 命令 文件操作
  13. 2020 智慧城市解决方案(智慧城市系统及相关技术)
  14. C语言实现一个关机程序
  15. 解决Worm.Win32.AutoRun.soq 病毒
  16. 【Java从零到架构师第③季】【30】SpringMVC-转发_重定向_路径问题总结
  17. 购物网站的商品推荐算法有哪些?
  18. Excel中如何快速输入☑和☒
  19. 宁夏召开外派教师家属新春慰问座谈会
  20. 基于Appfuse的Web应用快速开发

热门文章

  1. nginx域名访问的白名单配置梳理
  2. 无人机测绘技术在测绘领域的应用
  3. NetSuite 使用公司间跨组织履行处理销售和退货
  4. solrcloud 高可用集群搭建加solr整合hbase以及向ganglia报告度量
  5. 记:《洛克菲勒留给儿子的38封信》-- 37
  6. YOLO系列标注文件txt标签类别索引批量修改脚本
  7. keepass2android坚果云,Keepass+坚果云:多平台密码无缝同步(补)
  8. data fastboot 擦除_Fastboot 常用命令
  9. android手机系统怎么刷机包,安卓系统的手机如何刷机
  10. all elements are null问题