情境:
在测试片段线程时,遇到了一个奇怪的问题。
我用Kotlin编写了一个片段,在onResume()中包含以下代码块:
override fun onResume() {
super.onResume()
val handlerThread = HandlerThread("Stuff")
handlerThread.start()
val handler = Handler(handlerThread.looper)
handler.post {
Thread.sleep(2000)
tv_name.setText("Something something : " + isMainThread())
}
}
isMainThread()是一个函数,用于检查当前线程是否为主线程,如下所示:
private fun isMainThread(): Boolean = Looper.myLooper() == Looper.getMainLooper()
我发现我的TextView在2秒钟后更新,显示的文本是“某些东西:false”。
看到false告诉我这个线程当前不是UI/Main线程。
我觉得这很奇怪,所以我创建了同样的片段,但是用Java编写,使用以下代码从onResume()中提取:
@Override
public void onResume() {
super.onResume();
HandlerThread handlerThread = new HandlerThread("stuff");
handlerThread.start();
new Handler(handlerThread.getLooper()).post(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
textView.setText("Something something...");
}
});
}
应用程序按预期崩溃,并显示以下异常:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7313)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1161)
我做了一些调查,但我并没有找到能够解释这个问题的东西。同时,请假设我的观点都正确地膨胀了。
问题:
在Kotlin编写的Fragment中的UI线程之外运行的runnable中修改TextView时,为什么我的应用程序不会崩溃?
如果有某个文档中解释了这个问题,请引用一下吗?
我实际上并不想在UI线程之外修改我的UI,我只是好奇这是为什么。
如果您需要更多信息,请告诉我。谢谢!
更新: 根据@Hong Duan提到的,requestLayout()没有被调用。这与Kotlin / Java无关,而是与TextView本身有关。
我犯了一个错误,没有意识到我Kotlin片段中的TextView具有“match_parent”的layout_width。而Java片段中的TextView具有“wrap_content”布局宽度。
简而言之,这是用户错误 + requestLayout(),其中线程检查并不总是发生。