gpt4 book ai didi

java - 处理程序更改 UI 导致 CalledFromWrongThreadException

转载 作者:行者123 更新时间:2023-11-29 09:02:32 25 4
gpt4 key购买 nike

我已经创建了一个可以从 Activity 中的任何地方访问的 Handler,并且还编写了一个方法来更轻松地调用处理程序:

private Handler textFromBGThread = new Handler() {
@Override
public void handleMessage (Message msg) {
// Get the string from the msg
String outputString = msg.getData().getString("Output");
// Find the TextView
TextView Output = (TextView)findViewById(R.id.ConsoleOutputView);
// Display the output
Log.i("TextOutput","About to display message: " + outputString);
Output.setText(Output.getText() + outputString);
Log.i("TextOutput","Message displayed");
}
};

private void TextOutputWrapper (String outputText) {
Message msg = new Message();
Bundle bndle = new Bundle();
bndle.putString("Output", "\n" + outputText);
msg.setData(bndle);
textFromBGThread.handleMessage(msg);
}

那么这可以从后台线程简单地调用:

TextOutputWrapper("Attemping to connect...");

这将工作 1 次以上,但是,实际的视觉变化将导致抛出 CalledFromWrongThreadException。作为 Java 和 Android 的新手,我很困惑为什么会这样。

我注意到,当调用之间的时间间隔稍长时,崩溃往往会发生,并且如果对 TextOutputWrapper(String) 的调用接连发生得非常快,那么它就会起作用。例如,这个:

int i = 0;
while (i < 200) {
TextOutputWrapper(String.valueOf(i));
i++;
}

工作正常。

查看 LogCat 后,垃圾收集器似乎释放了一些资源,然后在下次调用 TextOutputWrapper(String) 时崩溃(当 Output.SetText(String) 被调用,准确地说),尽管我不确定为什么会导致此错误。

最佳答案

这里有一些我要更改的地方:

使用处理程序

Handler 如果您想触发 UI 更新并从非 UI 线程(又名)执行此操作,则很有用背景”线程)。

在您的情况下,它不符合该目的。您正在直接调用

textFromBGThread.handleMessage(msg);

它不是为您设计的。您应该使用 Handler 的方式是在 handleMessage(Message) 方法中实现您想要对 UI 执行的操作。你做到了。但是,您不应该直接调用handleMessage()。如果您这样做,那么 handleMessage() 将从调用 TextOutputWrapper() 的任何线程调用。 如果那是后台线程,那就错了。

您要做的是调用处理程序的 sendMessage(Message)方法(或其他可用变体之一)。 sendMessage() 会将您的消息放入线程安全的队列中,然后在主线程上进行处理。然后主线程将调用您的处理程序的 handleMessage(),将其传回排队的消息,并允许它安全地更改 UI。因此,更改 TextOutputWrapper() 以使用它:

private void TextOutputWrapper (String outputText) {
Message msg = new Message();
Bundle bndle = new Bundle();
bndle.putString("Output", "\n" + outputText);
msg.setData(bndle);
textFromBGThread.sendMessage(msg);
}

Java 约定

对于有经验的 Java 开发人员来说,这段代码有点难读。在 Java 中,typical coding standards为类之类的东西保留大写名称,而方法以小写字母开头。因此,请将该方法重命名为:

private void textOutputWrapper (String outputText);

或者,更好的是,因为这实际上是一个方法,而不是包装器,本身,重命名为类似

private void outputText(String text);

安全线程替代方案

最后,如果您只是想要一种允许您从任何线程安全地修改 UI 的方法,我可能会建议您使用另一种技术。我发现 Handler 对初学者来说不是那么容易使用。

private void outputText(final String outputString) {
runOnUiThread(new Runnable() {
@Override
public void run() {
// Find the TextView
TextView output = (TextView)findViewById(R.id.ConsoleOutputView);
// Display the output
Log.i("TextOutput","About to display message: " + outputString);
output.setText(Output.getText() + outputString);
Log.i("TextOutput","Message displayed");
}
});
}

runOnUiThread() 是每个 Activity 中可用的方法。

我还将向您指出一些有关了解 Android 中线程的一般文档:

http://www.vogella.com/articles/AndroidBackgroundProcessing/article.html

http://android-developers.blogspot.com/2009/05/painless-threading.html

关于java - 处理程序更改 UI 导致 CalledFromWrongThreadException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16513948/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com