子线程是否可以更新UI-Android
Posted hequnwang10
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了子线程是否可以更新UI-Android相关的知识,希望对你有一定的参考价值。
android 中子线程在满足一定的条件下可以更新 UI。
首先说一下抛出异常at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7905)
@Override
public void requestLayout()
if (!mHandlingLayoutInLayoutRequest)
checkThread();
mLayoutRequested = true;
scheduleTraversals();
void checkThread()
if (mThread != Thread.currentThread())
throw new CalledFromWrongThreadException(
"Only the original thread that created a view hierarchy can touch its views.");
当访问 UI 时,ViewRootImpl 会调用 checkThread 方法去检查当前访问 UI 的线程是否为创建 UI 的那个线程,如果不是。则会抛出异常。
scheduleTraversals()里是对View进行绘制操作,而在绘制之前都会检查当前线程是否为主线程mThread,如果不是主线程,就抛出异常;这样做法就限制了开发者在子线程中更新UI的操作;
但是为什么最开始的在onCreate()里子线程对UI的操作没有报错呢,可以设想一下是因为ViewRootImp此时还没有创建,还未进行当前线程的判断;
ViewRootImp在何时创建
从Activity启动过程中寻找源码,通过分析可以查看ActivityThread.java源码,并找到handleResumeActivity方法:
final void handleResumeActivity(IBinder token,boolean clearHide, boolean isForward, boolean reallyResume)
···
// TODO Push resumeArgs into the activity for consideration
ActivityClientRecord r = performResumeActivity(token, clearHide);
if (r.window == null && !a.mFinished && willBeVisible)
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient)
a.mWindowAdded = true;
wm.addView(decor, l);
else if (!willBeVisible)
if (localLOGV) Slog.v(
TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
···
内部调用了performResumeActivity方法。
从源码分析可得知,ViewRootImpl对象是在onResume方法回调之后才创建,那么就说明了为什么在生命周期的onCreate方法里,甚至是onResume方法里都可以实现子线程更新UI,因为此时还没有创建ViewRootImpl对象,并不会进行是否为主线程的判断;因此在onCreate()、onStart()、onResume()中可以做子线程更新UI
下面方法可以用来在子线程更新UI
- new Handler(getMainLooper).post(new Runnable()
- runOnUiThread(new Runable)
- 通过handler发送message来更新Ui
其实runOnUiThread内部就是调用new Handler(getMainLooper).post,而new Handler(getMainLooper).post内部调用的是sendMessageDelayed,所以更新Ui的原理就是通过handler发送message
开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系以上是关于子线程是否可以更新UI-Android的主要内容,如果未能解决你的问题,请参考以下文章