Android为什么不能在子线程更新UI

简介: Android为什么不能在子线程更新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


目录
相关文章
|
5天前
|
缓存 调度 Android开发
Android 在子线程更新 View
【10月更文挑战第21天】在 Android 开发中,虽然不能直接在子线程更新 View,但通过使用 Handler、AsyncTask 或 RxJava 等方法,可以实现子线程操作并在主线程更新 View 的目的。在实际应用中,需要根据具体情况选择合适的方法,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在子线程更新 View 的技巧和方法,为开发高质量的 Android 应用提供支持。
8 2
|
2月前
|
XML Android开发 UED
💥Android UI设计新风尚!掌握Material Design精髓,让你的界面颜值爆表!🎨
随着移动应用市场的蓬勃发展,用户对界面设计的要求日益提高。为此,掌握由Google推出的Material Design设计语言成为提升应用颜值和用户体验的关键。本文将带你深入了解Material Design的核心原则,如真实感、统一性和创新性,并通过丰富的组件库及示例代码,助你轻松打造美观且一致的应用界面。无论是色彩搭配还是动画效果,Material Design都能为你的Android应用增添无限魅力。
51 1
|
3月前
|
存储 搜索推荐 Java
探索安卓开发中的自定义视图:打造个性化UI组件Java中的异常处理:从基础到高级
【8月更文挑战第29天】在安卓应用的海洋中,一个独特的用户界面(UI)能让应用脱颖而出。自定义视图是实现这一目标的强大工具。本文将通过一个简单的自定义计数器视图示例,展示如何从零开始创建一个具有独特风格和功能的安卓UI组件,并讨论在此过程中涉及的设计原则、性能优化和兼容性问题。准备好让你的应用与众不同了吗?让我们开始吧!
|
3月前
|
编解码 Android开发
【Android Studio】使用UI工具绘制,ConstraintLayout 限制性布局,快速上手
本文介绍了Android Studio中使用ConstraintLayout布局的方法,通过创建布局文件、设置控件约束等步骤,快速上手UI设计,并提供了一个TV Launcher界面布局的绘制示例。
49 1
|
3月前
|
API Android开发
Android项目架构设计问题之选择和使用合适的UI库如何解决
Android项目架构设计问题之选择和使用合适的UI库如何解决
43 0
|
4月前
|
XML Android开发 UED
💥Android UI设计新风尚!掌握Material Design精髓,让你的界面颜值爆表!🎨
【7月更文挑战第28天】随着移动应用市场的发展,用户对界面设计的要求不断提高。Material Design是由Google推出的设计语言,强调真实感、统一性和创新性,通过模拟纸张和墨水的物理属性创造沉浸式体验。它注重色彩、排版、图标和布局的一致性,确保跨设备的统一视觉风格。Android Studio提供了丰富的Material Design组件库,如按钮、卡片等,易于使用且美观。
127 1
|
5月前
|
Android开发 开发者
Android UI设计中,Theme定义了Activity的视觉风格,包括颜色、字体、窗口样式等,定义在`styles.xml`。
【6月更文挑战第26天】Android UI设计中,Theme定义了Activity的视觉风格,包括颜色、字体、窗口样式等,定义在`styles.xml`。要更改主题,首先在该文件中创建新主题,如`MyAppTheme`,覆盖所需属性。然后,在`AndroidManifest.xml`中应用主题至应用或特定Activity。运行时切换主题可通过重新设置并重启Activity实现,或使用`setTheme`和`recreate()`方法。这允许开发者定制界面并与品牌指南匹配,或提供多主题选项。
71 6
|
5月前
|
开发工具 Android开发 开发者
Android `.9.png` 图像是用于UI的可拉伸格式,保持元素清晰度和比例
【6月更文挑战第26天】Android `.9.png` 图像是用于UI的可拉伸格式,保持元素清晰度和比例。通过边上的黑线定义拉伸区域,右下角黑点标识内容区域,适应文本或组件大小变化。常用于按钮、背景等,确保跨屏幕尺寸显示质量。Android SDK 提供`draw9patch.bat`工具来创建和编辑。**
248 6
|
5月前
|
API Android开发 开发者
`RecyclerView`是Android API 21引入的UI组件,用于替代ListView和GridView
【6月更文挑战第26天】`RecyclerView`是Android API 21引入的UI组件,用于替代ListView和GridView。它提供高效的数据视图复用,优化的布局管理,支持多种布局(如线性、网格),并解耦数据、适配器和视图。RecyclerView的灵活性、性能(如局部刷新和动画支持)和扩展性使其成为现代Android开发的首选,特别是在处理大规模数据集时。
60 2
|
6月前
|
前端开发 搜索推荐 开发者
SAP UI5 sap.m.Column 控件的 minScreenWidth 属性介绍
SAP UI5 sap.m.Column 控件的 minScreenWidth 属性介绍