android - TextView 可从线程操作

标签 android multithreading

我需要帮助理解使用线程进行 View 操作。我有 TextView ,我想从 Thread 操作其文本。这是我的代码:

Thread thread = new Thread(new Runnable(){

        @Override
        public void run() {

            mTextView.setText("foo");
        }
    });

thread.run();

我最初的理解是 View 不能从后台线程操作。但这个示例确实将 TextView 的文本更改为“foo”:这种情况到底发生了什么?我在 Activity 的 onCreate 方法中运行了这个。

这是否意味着这里的 TextView 确实是在 UI 线程上操作的?如果我错过了一些非常明显的东西,请道歉。

最佳答案

问题是您以错误的方式启动线程。 您调用thread.run()这只是执行 run() UI 线程中的方法。 如果你想执行一个单独的线程,你应该调用 thread.start() 。这就是它的工作原理。

在这种情况下,您将捕获在 UI 线程之外访问 UI 元素的异常。

编辑

此外,您可能在 onCreate() 内执行代码方法。 该线程花费的时间很少,因此如果它在 onCreate() 内部方法,它在 UI 出现在屏幕上之前就完成了。

如果将代码移至onResume()例如,并在 run() 中添加一些 sleep 代码访问之前的方法TextView ,像这样:

try {
    Thread.sleep(5000);
} catch (InterruptedException e) {
    e.printStackTrace();
}

它会崩溃。

编辑2

Does this imply that a new thread isn't allocated from the thread pool until after a certain period of time elapses ?

没有。新线程分配不依赖于时间。 它开始了……一旦开始了。 问题是它执行得太快。

不失一般性,让我们继续 TextView作为我推理的一个主题。 TextView是普通类。您创建该类的实例并使用它来操作相应的低级 UI 元素。当您将新文本分配给 TextView 时会发生什么?首先,新值被写入其实例字段。然后,您的实例会触发相应的低级 UI 元素,例如:“嘿,我的状态已更改。请在屏幕上更新它。”如果屏幕可见,则 UI 元素会说:“好的,明白了”,获取新值并自行更新。但如果屏幕不可见,则意味着 UI 元素还不存在。没有人回答,扳机也无效。 这是主要部分。当您调用setText()时,所有这一切都会发生方法TextView类(class)。但只有“更新 UI 元素”部分是禁止在非 UI 线程中执行的。访问和更改TextView's来自单独线程的实例字段完全合法。问题是,缺一不可。

那么为什么在我们的情况下它没有崩溃呢? 我们的线程只做一件事 - 文本更改,因此它完成得非常快,甚至早于 onCreate()方法返回。并且因为 UI 仅在 onResume() 之后才变得可见。方法返回时,您的“从单独的非 UI 线程访问 UI 元素”实际上与 UI 无关,因为该 UI 甚至还不存在,因此您的更改不会触发任何 UI 元素。但是当 UI 实际变得可见时,它只是读取 TextView 的当前状态。实例 - 已更改为新值 - 并在 UI 线程中更新自身。

通常,甚至将您的线程放入 onResume()方法不保证它会在 onResume() 之后完成方法返回。 通过添加Thread.sleep(...)方法进入我们的线程,我们只是给它一些时间和机会保持活力,直到 onResume()返回,实际的 UI 被加载并出现在屏幕上。发生这种情况后,“仅从 UI 线程访问 UI”规则 生效并使应用程序崩溃。

通常我们不需要人为地延长线程的生命周期来捕获崩溃,就像在这种情况下一样,因为通常我们正在使用的 Activity 或 fragment 已经运行了一段时间,并且它们的 UI 是已经可见。

所以重点是 UI 是否在非 UI 线程能够访问它之前变得可见。

如果我错了,有人纠正我,但这是我对这一切的理解。

关于android - TextView 可从线程操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32136353/

相关文章:

android 在 editText 上应用函数

javascript - 在 Android 中通过 Javascript 隐藏/显示 WebView

multithreading - 向量中函数的线程调用

objective-c - Cocoa:处理线程结果,并对多个工作表进行排队

c# - 如何重新启动线程或任何其他替代解决方案

android - 如何在 Android 的 ndk-gdb 中调用 malloc()

android - 在 GCM onMessage() 中显示对话框

android - 当用户使用自动填充时,将焦点设置在下一个 TextInput 上

php - apache php > 用户请求

c++ - 将 std::future 和 std::promise 与非 std::thread 一起使用是否安全?