为什么都要在主线程中更新UI

在 iOS开发过程中,我一直知道更新UI需要在主线程中,但也没怎么细想为什么要在主线程中,或者说为什么不能在子线程中更新UI。今天抽空自己在网上查查资料 ,了解一下这个问题。

像UIKit这样大的框架上确保线程安全是一个重大的任务,会带来巨大的成本。UIKit不是线程安全的,假如在两个线程中设置了同一张背景图片,很有可能就会由于背景图片被释放两次,使得程序崩溃。或者某一个线程中遍历找寻某个subView,然而在另一个线程中删除了该subView,那么就会造成错乱。apple有对大部分的绘图方法和诸如UIColor等类改写成线程安全可用,可还是建议将UI操作保证在主线程中。

事实上在子线程中如果要对其他UI 进行更新,必须等到该子线程运行结束,而对响应用户点击的Button的UI更新则是及时的,不管他是在主线程还是在子线程中做的更新,意义都不大了,因为子线程中对所有其他ui更新都要等到该子线程生命周期结束才进行。

在子线程中是不能进行UI 更新的,我们看到的UI更新其实是子线程代码执行完毕了,又自动进入到了主线程,执行了子线程中的UI更新的函数栈,这中间的时间非常的短,就让大家误以为分线程可以更新UI。如果子线程一直在运行,则子线程中的UI更新的函数栈 主线程无法获知,即无法更新。只有极少数的UI能直接进行UI更新,因为开辟线程时会获取当前环境,如点击某个按钮,这个按钮响应的方法是开辟一个子线程,在子线程中对该按钮进行UI 更新是能及时的,如上面的换背景图,但这没有任何意义。

时间: 2024-10-28 19:36:17

为什么都要在主线程中更新UI的相关文章

【iOS开发-95】JSON反序列化、XML数据解析以及主线程中的UI更新等小细节

我们发送请求后,一般会获得data数据,这个时候我们反序列化即可. 常用的数据格式之一是JSON,格式如: {key:value,key:value,key:value....} (1)因为iOS5之前苹果不支持JSON解析,所以催生很多第三方解析,SBJson以及JSONKit.简单地JSON反序列化示例如下: NSURL *url=[NSURL URLWithString:@"http://www.baidu.com"]; NSURLRequest *request=[NSURLR

Android新线程中更新主线程中的UI控件

Android中的View都不是线程安全的,所以如果在某一个新线程中直接更新主线程中的UI控件时就会报如下错误: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 为了解决在另一个线程中更新UI控件的问题,我们可以使用如下几种解决方案: 1. 自己写Handler解决,参见<And

使用Handler在子线程中更新UI

Android规定只能在主线程中更新UI,如果在子线程中更新UI 的话会提示如下错误:Only the original thread that created a view hierachy can touch its view((只有原来的线程创建一个视图层次可以触摸它的视图). 只能在主线程中更新UI的原因是:android中相关的view和控件不是线程安全的,我们必须单独做处理. 有的时候需要再子线程中实现更新UI,下面介绍使用Handler实现线程通信的特点实现在子线程中更新UI. H

android 不能在子线程中更新ui的讨论和分析

问题描述 做过android开发基本都遇见过ViewRootImpl$CalledFromWrongThreadException,上网一查,得到结果基本都是只能在主线程中更改ui,子线程要修改ui只能post到主线程或者使用handler之类.但是仔细看看exception的描述并不是这样的,"Only the original thread that created a view hierarchy can touch its views",只有创建该 view 布局层次的原始线程

网络操作不能直接写在主线程中 以及 为什么不能在子线程中更新UI控件的属性

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ //注意: 所有网络操作不能直接写在主线程中 因为所有的网络操作都是耗时的,如果加载到主线程中,会导致与用户的交互出现问题 ,所以要加载到子线程中 // [self loadImage]; [self performSelectorInBackground:@selector(loadImage) withObject:nil]; } //加

用Handler的post()方法来传递线程中的代码段到主线程中执行

自定义的线程中是不能更新UI的,但是如果遇到更新UI的事情,我们可以用handler的post()方法来将更新UI的方法体,直接传送到主线程中,这样就能直接更新UI了.Handler的post()方法就是将Runnable中的代码段传送到主线程. 布局文件就是个textView,我就不贴了. 全部代码 package com.kale.handler; import android.app.Activity; import android.graphics.Color; import andro

在用户线程/主线程中推荐MsgWaitForMultipleObjects代替WaitForSingleObject和WaitForMultipleObjects()函数

在多线程编程中,通常都需要线程间的同步,一个线程要等待另一个线程的事件才继续执行,一般的做法是采用WaitForSingleObject和WaitForMultipleObjects()函数来实现. 但在实际的应用中,经常出现等待线程卡死的状况,也就是说等待的事件一直无效.为什么事件一直无效呢?很多的情况是等待线程阻塞了另外的线程,使另外的线程无法设置事件有效.为什么会阻塞呢?原因就比较多了,需要具体问题具体分析. WaitForSingleObject和WaitForMultipleObjec

在子线程中更改主线程中的控件的信息,在子线程中用toast

一丶在子线程中不允许更改主线程中的控件的信息,也不允许在子线程中用toast,我们要更改的话 (1)消息机制:使用handler (由主线程调用) 在主程序中Handler handler = new Handler(){ public void handleMessage(Message msg){ int type = msg.what ;//拿到msg的类型,再判断            switch (type) {                case SUCCESS:      

Android中,子线程使用主线程中的组件出现问题的解决方法

Android中,主线程中的组件,不能被子线程调用,否则就会出现异常. 这里所使用的方法就是利用Handler类中的Callback(),接受线程中的Message类发来的消息,然后把所要在线程中执行的功能交由Handler类来处理.这样就解决了线程出现的问题. 下面测试实例功能为单击图片,图片透明度改变为50,300毫秒后恢复不透明,代码如下: public class Demo extends Activity{ private ImageView changeImg = null;//Im