-
Notifications
You must be signed in to change notification settings - Fork 784
2019-07-05:子线程能否更新UI?为什么? #91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
可以更新UI但是不推荐,因为很容易造成carsh。因为Android会checkThread,可以尝试一下在子线程更新setText(),文字是会改变的,但紧接着就会报异常。 |
|
不可以,因为会出现异常情况;在子线程中更新完后会出现异常现象如下: |
子线程是不能直接更新UI的 注意这句话,是不能直接更新,不是不能更新(极端情况下可更新) 绘制过程要保持同步(否则页面不流畅),而我们的主线程负责绘制ui,极端情况就是,在Activity的onResume(含)之前的生命周期中子线程都可以进行更新ui,也就是 onCreate,onStart和onResume,此时主线程的绘制还没开始。 |
不能直接更新,更新方式有三种
});` |
不能直接更新Ui,直接更新会崩溃,但你更改的内容还是会变化的,因为你子线程更新了,但此时主线程不知道,主线程用来绘制ui,所以会崩溃。下面方法可以用来在子线程更新UI
|
这句话应该改成: 不能更新非本线程创建的View |
源码里面的注释是只能创建view的线程去更新该view,所以理论上是可以子线程创建,然后子线程更新的,但有个问题:子线程创建的View可以不通过主线程显示吗?如果不能越过主线程显示,那结果等价于子线程不能更新UI,因为不能被看到的View毫无意义啊。 |
后来想了想,我说的这句话也不对,为何不能更新主线程的view,源自于 ViewRootImp 对线程做了校验,那么如果 创建一个View,不显示出来,也就没有了ViewRootImp中的线程校验,所以略尴尬=.= 也就是说,如果一个View没有被add到 window中,其实就是通过ViewRootImp.setView 添加到window中,那么就不存在 线程校验这回事 那么我们什么时候需要一个不存在于页面上的View呢??? 我目前最常用的是拼图=.=,生成一个view 然后截图 |
再补充一点,有一种 子线程可以更新主线程View的方法就是 在view被添加进window之前,应该是在onResume之前吧,忘记了,有兴趣的可以看看activity 启动源码 |
我翻到了上面有个哥子发了篇博客,博客里说到了更新ui时通常会调用requestLayout方法,最终调用到ViewRootImpl的requestLayout方法。
只要条件判断不成立,就能跳过线程检查的步骤。 这个无疑是对更新逻辑的利用,但是仍旧无法实现直接在子线程直接更新UI,也并没有回答让子线程创建的View在window中显示出来,并且还能更新UI的问题。 |
checkThread发送在viewRootImpl,其在onResume时创建 子线程在初始化looper且looper.loop开启循环 把子线程运行在oncreate时机更新UI也应该可以 |
只要操作的View没有被添加到ViewRootImpl中,可以随意在任何线程中操作UI |
子线程能更新UI,但是不推荐这么做。一般说的子线程不能更新UI,是因为执行更新UI操作的时候会进行checkThread检查,checkThread判断如果当前线程不是UI线程就会抛出异常。而checkThread跟ViewRootImpl这个类的对象有关,那么只要ViewRootImpl的对象还未创建,就无法执行checkThread,也就是在子线程更新UI也不会报错。ViewRootImpl的对象是在onResume()之后创建的,因此在onCreate()、onStart()、onResume()中可以做子线程更新UI |
在子线程里更新TextView内容有以下两种场景是不会抛出异常的: 结论:在子线程操作View 确实不一定导致Crash,那是因为刚好满足一定的条件没有触发checkThread机制,但这并不代表我们在开发过程中可以这么写。 |
子线程是不能用于更新UI的 在子线程更新UI会导致应用崩溃 如果想更新UI就要切换到主线程来更新 |
子线程可以在ViewRootImpl还没有被创建之前更新UI; |
发散一下思维 , Android禁止在子线程更新UI的根本原因是为了维持单线程更新UI,为什么不能多线程更新UI需要认真考虑其缺点和优点 |
想想 Toast,Toast 可不可以在子线程弹出呢,答案是可以的,Toast 中 View 创建的时候所处的线程是子线程,弹出时进行checkThread 检查也会直接通过,最后添加到 wms 中,就可以显示出来 |
这是来自QQ邮箱的假期自动回复邮件。
|
这是来自QQ邮箱的假期自动回复邮件。
您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。
|
No description provided.
The text was updated successfully, but these errors were encountered: