首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

当一个新线程立即操作UI时,为什么没有CalledFromWrongThreadException?

当一个新线程立即操作UI时,没有出现CalledFromWrongThreadException的原因是因为在Android中,UI操作必须在主线程(也称为UI线程)中执行。如果在非主线程中直接操作UI,就会抛出CalledFromWrongThreadException异常。

Android系统通过一个消息队列(Message Queue)来管理UI线程中的消息和事件。当我们在主线程中执行UI操作时,实际上是将操作封装成一个消息,然后加入到消息队列中。然后,UI线程会按照队列中的顺序依次处理这些消息,从而实现UI的更新。

而当我们在新线程中尝试直接操作UI时,由于不是在UI线程中执行,就无法将操作封装成消息加入到消息队列中。这就导致了在非主线程中直接操作UI会引发CalledFromWrongThreadException异常。

为了解决这个问题,Android提供了一些方法来在新线程中更新UI。其中最常用的方法是使用Handler或者AsyncTask。通过Handler,我们可以将需要在UI线程中执行的操作封装成消息发送给UI线程,然后由UI线程处理这些消息并更新UI。而AsyncTask则是一种更方便的方式,它封装了Handler的使用,可以更简洁地在新线程中执行后台任务并更新UI。

总结起来,没有出现CalledFromWrongThreadException的原因是因为在新线程中没有直接操作UI,而是通过合适的方式将操作封装成消息发送给UI线程,在UI线程中执行。这样可以保证UI操作在主线程中进行,避免了线程安全问题和UI更新的冲突。

腾讯云相关产品和产品介绍链接地址:

  • 腾讯云消息队列 CMQ:https://cloud.tencent.com/product/cmq
  • 腾讯云云函数 SCF:https://cloud.tencent.com/product/scf
  • 腾讯云移动推送 TPNS:https://cloud.tencent.com/product/tpns
相关搜索:当线程没有阻塞时,为什么还要调用nativeWake()呢?当工作线程有一个无限的while循环时,为什么要分离工作线程呢?当从一个类调用Print()时,为什么没有任何东西返回?为什么当新表单打开时,其中一个按钮会以蓝色突出显示?当操作按钮被点击时,如何在R中打开一个新的浏览器?当另一个线程处于活动状态时,为什么不在全局对象上调用__del__?当I/O操作在同步方法中完成时,它是否总是会产生一个新线程?当我从componentWillMount()调用一个操作时,为什么我的连接状态没有更新?Flutter:当创建新的仿真器时,它显示错误,因为没有可用的设备定义,为什么?当一个用户表单被卸载时,为什么相关的对象没有被设置为空?当分配一个新的属性给一个函数时,我如何抑制来自mypy的“没有属性”的错误?当一个按钮被点击时,我的代码应该会创建一个.txt文件--但它没有。为什么?当从选择框中选择一个项目时,为什么component类中的方法没有被调用?当当前正在执行的线程进入等待状态时,为什么runOn()方法不在池中的下一个可用线程上执行映射操作符?为什么当AttributeError是一个字符串时,'str‘对象没有' decode’属性会发生?当通过调用Task.Run和ThreadPool.QueueUserWorkItem来排队到ThreadPool时,为什么线程计数会增加一个以上?VueJS -当子组件中的数据用作另一个组件中的数据时,为什么子组件中的数据没有正确更新?为什么会有一个词法错误:当json_string通过curl发送时,json文本中的字符无效,但在R控制台中没有?
相关搜索:
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Android 子线程 UI 操作真的不可以?

3.2 CalledFromWrongThreadException来自哪里 众所周知,我们在更新界面元素,若不在主线程执行,系统会抛CalledFromWrongThreadException,观察异常堆栈...也就是说一个View由于其关联的ViewRootImpl对象,才有可能触发CalledFromWrongThreadException异常,因此attachInfo是View继续有效执行invalidate...仅在view被attach至window,它才会作为UI的一部分(挂载至ViewTree),需要被固定线程进行控制、更新等管理操作。...四、编码验证与实践 其实实际中屏幕内容的绘制从来都不是完全在一个线程中完成的,最常见的场景比如: 视频播放,视频画面的绘制并不是App的主线程UI线程。...参考: Android 屏幕刷新机制 为什么Android必须在主线程更新UI

1K40
  • 可能是全网最简单透彻的安卓子线程更新 UI 解析

    相信下面的代码大家看过很多遍了,在 onCreate() 生命周期里开启一个线程来更新 UI ,居然没有闪退和异常( 在大概率情况下是没有问题的 ) @Override protected...UI"); Log.e("MyButton", "子线程更新UI"); } }).start(); } 我们在子线程里睡眠一秒试试看...= null) mEditor.prepareCursorControllers(); 3708 } 这个方法是关键, mLayout 不为空才会进入,我们进入 checkForRelayout...mLayout 不为空才会进入,而事实上只有 View 在 测量 方法里才会对这个值进行赋值,答案也就很明显了,当我们在子线程里 setText 的时候,其实只是简单的设置了这个控件要显示的值,并不会立即去显示...最后扩展一下,如果就是想在子线程里更新 UI 怎么办呢,在onResume 之前就行,或者把 View 的 ViewRootImpl 实例化放到子线程来进行,这样就不会因为非 UI 线程抛出异常。

    1.1K10

    笔记16 | 解析和练习AsyncTask

    前言 本节给大家带来的是Android给我们提供的一个轻量级的用于处理异步任务的类:AsyncTask,我们一般是 继承AsyncTask,然后在类中实现异步操作,然后将异步执行的进度,反馈给UI线程...2)同步与异步的概念: 同步:当我们执行某个功能,在没有得到结果之前,这个调用就不能返回!...直到你把 套套买回来带上,这个时候就可以开始啪啪啪了~一个形象地例子,♪(^∇^*) 异步:和同步则是相对的,当我们执行某个功能后,我们并不需要立即得到结果,我们额可以正常地 做其他操作,这个功能可以在完成后通知或者回调来告诉我们...有时我们也把他称作UI线程!而在Android App我们必须遵守这个单线程模型的规则: Android UI操作并不是线程安全的并且这些操作都需要在UI线程中执行!...假如我们在非UI线程中,比如在主线程中new Thread()另外开辟一个线程,然后直接在里面修改UI控件的值; 此时会抛出下述异常: android.view.ViewRoot$CalledFromWrongThreadException

    57560

    关于 Android 进程和线程,你必须了解的东西

    前言 按照操作系统中的描述。线程是 CPU 调度的最小单元,同时线程也是一种有限的资源。而进程一般指一个执行单元,在 PC 和移动设备上指一个程序或者一个应用。一个进程可以包含多个线程。...进程 ---- 一个程序第一次启动的时候,Android 会启动一个 Linux 进程和一个线程。默认情况下,同一应用的所有组件均在相同的进程中运行,且大多数应用都不会改变这一点。...比较常见的使用场景 由于运行服务的进程级别高于托管后台 Activity 的进程,因此启动长时间运行操作的 Activity 最好为此操作启动服务,而不是简单地创建工作线程操作有可能比 Activity...从任务执行的角度来看,IntentService 的作用很像一个后台线程,但是 IntentService 是一种服务,它不容易被系统杀死从而可以尽量保证任务的执行,而如果是一个后台线程的话,由于这个时候进程中没有活动的四大组件...这是因为 Android 的 UI 控件不是线程安全的,如果在多线程中并发访问可能会导致 UI 控件处于不可预期的状态,那为什么系统不对 UI 控件的访问加上锁机制呢?

    83020

    笔记55 | 处理CalledFromWrongThreadException错误问题

    报错说明 直接在子线程更新UI会报CalledFromWrongThreadException错,错误如下: 12-20 15:39:04.730: E/AndroidRuntime(2763):...FATAL EXCEPTION: Timer-0 12-20 15:39:04.730: E/AndroidRuntime(2763): android.view.ViewRootImpl$CalledFromWrongThreadException...72) 12-20 15:39:04.730: E/AndroidRuntime(2763): at java.util.Timer$TimerImpl.run(Timer.java:284) 为什么会出现这个问题...,这里有一篇大神的解答关于为什么不能再子线程中更新UI的讨论大神对代码的解读能力让人兴叹,总结来说是因为子线程没有创建Looper.prepare()这个与子线程不能Toast的问题是一样的Toast为什么不可以在子线程里面运行...这样Runnable对像就能在ui程序中被调用 public class MainActivity extends Activity { @Override protected void

    1.6K40

    线程能否操作UI控件

    前言 这是一个初级Android工程师面试问题,一般标准答案:子线程不能操作UI控件。 那我为什么还要问这个弱智的问题呢? 因为我心目中的标准答案:子线程不能操作"参与绘制"的UI控件。...一、什么是操作UI 如何理解我的标准答案,首先回答一下,什么叫做操作UI ?...= Thread.currentThread()) {//mThread为主线程,也就是UI线程 //子线程就抛出异常了 throw new CalledFromWrongThreadException...四、什么是参与绘制 看完上面的内容,肯定有人说答案不就是子线程不能操作UI控件嘛,为什么还要加上"参与绘制"的条件。...4.2.1 什么情况下View没有ViewParent: 我们new了一个View还没有addView到一个ViewParent 4.2.2 什么情况下最顶层的ViewParent不是ViewRootImpl

    78210

    2014-10-27Android学习------程序源码+知识总结------城市列表应用程序

    比如在修改某个view的显示,调用invalidate()才能看到重新绘制的界面。invalidate()的调用是把之前的旧的view从主UI线程队列中pop掉。...3、setVisibility()方法 : View可视状态在INVISIBLE转换VISIBLE,会间接调用invalidate()方法, 继而绘制该View...Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用...说白了就是注意一点:invalidate不能再线程中直接使用,但是可以在UI线程中直接使用,postinvalidate可以直接在线程中使用 我们在应用程序中类是继承View的,它就是一个UI线程,那么它就可以直接使用了...View发生改变UI进行重绘。

    30330

    Android 进程和线程模型

    需要执行应用程序中的代码,Android会启动一个jvm,即一个的进程来执行,因此不同的apk运行在相互隔离的环境中。...一个程序第一次启动,Android会同时启动一个对应的主线程(Main Thread),主线程主要负责处理与UI相关的事件,如:用户的按键事件,用户接触屏幕的事件以及屏幕绘图事件,并把相关的事件分发到对应的组件进行处理...如果在非UI线程中直接操作UI线程,会抛出android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that...由于UI线程负责事件的监听和绘图,因此,必须保证UI线程能够随时响应用户的需求,UI线程里的操作应该向中断事件那样短小,费时的操作(如网络连接)需要另开线程,否则,如果UI线程超过5s没有响应用户请求,...点击一个按钮后启动线程线程执行结束后通过handler发送一个消息,由于这个handler属于UI线程,因此这个消息也发送给UI线程,然后UI线程又把这个消息给handler处理,而这个handler

    1.5K20

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

    Android消息处理机制(Handler、Looper、MessageQueue与Message)已经被问烂了,那我们今天来谈谈为什么需要主线程更新UI,子线程不能更新UI?...1)首先,并非在子线程里面更新UI就一定有问题,如下所示的代码,则可以完美更新UI。...总结一下就是在刷新页面前会判断当前是否在主线程,如果不在主线程则抛异常,所以我们开始学Android的时候,别人就告诉我们:更新UI一定要在主线程。 那为什么上面第一次没有线程等待的时候没有报错呢?...到这里可以事后一支烟了,不是,是总结一下了: 1)ViewRootImpl是在Activity的onResume()方法后面创建出来的,所以在onResume之前的UI更新可以在子线程操作而不报错,因为这个时候...2)安卓系统中,操作viwe对象没有加锁,所以如果在子线程中更新UI,会出现多线程并发的问题,导致页面展示异常。 小伙子分析得很不错,把我打动了,回去等offer吧。

    85201

    Android子线程与更新UI问题的深入讲解

    前言 在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法。...UI吗,为什么情形一可以正常运行,情形二不能正常运行呢; 子线程修改UI出现异常,与什么方法有关 首先从出现异常的log日志入手,发现出现异常的方法调用顺序如下: TextView.setText...()方法,一直调用下去,直到调用到ViewRootImp的requestLayout方法; 2.ViewRootImp的requetLayout方法,主要有两部操作一个是checkThread()方法...,检测线程一个是scheduleTraversals,执行绘制相关工作; 情形3 @Override protected void onCreate(Bundle savedInstanceState...= Thread.currentThread()判断为true,所以不会抛出只能在主线程更新UI的异常。

    1.2K30

    关于Android中为什么线程不会因为Looper.loop()里的死循环卡死?引发的思考,事实可能不是一个 epoll 那么 简单。

    3,网传的观点大概如下:         1.handler机制是使用pipe来实现的         2.主线程没有消息处理阻塞在管道的读端         3.binder线程会往主线程消息队列里添加消息...SurfaceFlinger 在启动时会先进行自己内部的一个工作线程实例化和运行,该线程在后面承担着整个的绘制事件流程,在运行该线程,会先进行MessageQueue内部的 looper 和 handler...而是限制了,如果ViewRootImpl是由子线程创造的,那么就可以在该子线程中发送更新UI的消息,自然地就能更新了,那么为什么限制呢?   ...显然两个线程不能同时draw,否则屏幕会花;不能同时insert map,否则内存会花;不能同时write buffer,否则文件会花。需要互斥,比如锁。结果就是同一刻只有一个线程可以做ui。...那么两个线程互斥几率较大,或者保证互斥的代码复杂,选择其中一个长期持有其他发消息就是典型的解决方案。所以普遍的要求ui只能单线程

    1.5K50

    Handler源码和9个常见问题的解答,这些你都掌握了吗?

    线程的如何更新UI,比如Dialog,Toast等?系统为什么不建议子线程中更新UI? 主线程如何访问网络? 如何处理Handler使用不当造成的内存泄漏?...-消费者模式,源源不断的生产消息,处理消息,没有消息进行休眠。...系统为什么不建议在子线程中访问UI? 这是因为 Android 的UI控件不是线程安全的,如果在多线程中并发访问可能会导致UI控件处于不可预期的状态,那么为什么系统不对UI控件的访问加上锁机制呢?...缺点有两个: 首先加上锁机制会让UI访问的逻辑变得复杂 锁机制会降低UI访问的效率,因为锁机制会阻塞某些线程的执行。 所以最简单且高效的方法就是采用单线程模型来处理UI操作。...同时还有一个很关键的点,如果有个延时消息,界面关闭,该Handler中的消息还没有处理完毕,那么最终这个消息是怎么处理的?

    1.3K00

    Android采坑之路(一):怀疑人生,主线程修改UI也会崩溃?

    五、发现原因 那么问题原因找到了: 是在项目子线程中有弹出过Toast,然后Toast并没有关闭,又在主线程弹出了同一个对象的toast,会造成崩溃。...此时内心有个困惑: 如果是子线程弹出Toast,那我就需要写Looper.prepare方法和Looper.loop方法,为什么我自己一点印象都没有。...Javabridge的回调中看到有任何准备Looper的地方,那么为什么Toast没有崩溃掉?...所以也难怪一方面奇怪自己怎么没有写Looper的印象,一方面又很好奇为什么这个线程在开发者没有准备Looper的情况下也能正常弹出Toast。 总结 至此,真相终于找出来了。...mThread保存起来,这样做就有可能会出现子线程更新UI操作

    4.9K20

    面试?看完这篇就够了-深入分析从点击应用图标到应用界面展示

    不过如果我们在代码中手动调用 View.requestLayout,最终也会走到这里,此时的当前线程就是调用线程,所以这也解释了为什么我们不能在非主线程更新 UI。一定不能在非主线程更新 UI 吗?...一个进程调用 fork() ,它会创建一个的子进程,子进程是父进程的副本,包括代码、数据、堆栈等。在 fork() 之后,父进程和子进程将并发执行相同的代码。...Zygote 进程在系统启动创建,它预加载了许多常用的类和资源,为应用程序进程提供了一个初始化好的运行环境。需要创建的应用程序进程,系统会通过 Zygote 进程来 fork 出新的进程。...通过 Zygote 进程 fork 出新的应用程序进程,新进程可以直接使用这些已加载的类和资源,无需再次加载。这样可以大大减少应用程序启动的类加载和资源初始化时间,提高启动速度。...创建之后,只需要保证创建 ViewRootImpl 的线程和更新 UI线程是同一个就可以;比如我们在子线程调用 ViewManager#addView我们同上说子线程不可以更新 UI,这个异常是在

    29730

    android消息机制入门

    直接运行会报错,Only the original thread that created can touch xxxxx,只有主线程才可以访问View对象,是因为线程的同步与互斥 内部实现更新界面的时候做了一个检查...,检查这个更新的操作是否是在Ui线程里面执行的,如果是没有任何问题,如果不是抛出一个运行时异常,CalledFromWrongThreadException 在上一节,我们在子线程里面访问网络之后,直接调用...ImageView对象的setImageBitmap()修改Ui界面了,所以会报错 我们需要,在子线程里面告诉主线程一个消息,我们要修改界面,把内容Bitmap传递给主线程,让他帮我们修改。...子线程通过Handle发送一条消息,消息被放到消息队列里面, 主线程里有一个Looper消息的轮询器 如果轮询器发现了的消息,调用Handle对象的handleMessage()来处理消息 Handler...是一个消息处理器必须在主线程里面new出来 ?

    61520

    想实现安卓队列功能?Handler内功心法,你值得拥有!——Handler源码和常见问题的解答

    线程的如何更新UI,比如Dialog,Toast等?系统为什么不建议子线程中更新UI? 主线程如何访问网络? 如何处理Handler使用不当造成的内存泄漏?...,没有消息进行休眠。...系统为什么不建议在子线程中访问UI? 这是因为 Android 的UI控件不是线程安全的,如果在多线程中并发访问可能会导致UI控件处于不可预期的状态,那么为什么系统不对UI控件的访问加上锁机制呢?...缺点有两个: 首先加上锁机制会让UI访问的逻辑变得复杂 锁机制会降低UI访问的效率,因为锁机制会阻塞某些线程的执行。 所以最简单且高效的方法就是采用单线程模型来处理UI操作。...同时还有一个很关键的点,如果有个延时消息,界面关闭,该Handler中的消息还没有处理完毕,那么最终这个消息是怎么处理的?

    2K20
    领券