【发布时间】:2017-06-20 16:19:00
【问题描述】:
我正在构建一个语法高亮源代码文件的应用程序。当用户单击文件时,我希望他们尽快看到代码,同时我在后台语法高亮代码(CPU 密集型)。这是我编写的代码(它使用 C#/Xamarin,但 Java 开发人员可以通过一些努力来翻译它):
private void DisplayContent(IColorTheme theme)
{
var text = new ColoredText(_content);
_editor.SetText(text, TextView.BufferType.Editable);
// The last param uses C# 7 syntax for tuples, don't worry about it
Task.Factory.StartNew(HighlightContent, state: (text, theme));
}
private void HighlightContent(object state)
{
var (text, theme) = ((ColoredText, IColorTheme))state;
using (var colorer = TextColorer.Create(text, theme))
{
GetHighlighter().Highlight(_content, colorer);
}
}
重要的部分是我首先用ColoredText 调用SetText(),这是一个自定义类型,只包装了SpannableStringBuilder。然后,我调用Task.Factory.StartNew,这是C# 中在新线程上运行回调(在本例中为HighlightContent)的一种方式。最后,GetHighlighter().Highlight(...) 完成了大部分工作,并在文本的底层SpannableStringBuilder 上调用了SetSpan 数千次。
当我运行我的应用程序时,我看到了文本,但它全是白色的。就好像我完全省略了所有语法高亮代码,只写了_editor.SetText(...)。我强烈怀疑这是因为SetSpan 正在另一个线程上运行。但是,我需要在不同的线程上运行SetSpan,因为通过分析我已经确定它占用了大量的 CPU 周期。如果我在 UI 线程上运行它,我的应用程序会因大文件而冻结。
如何让SetSpan 从非 UI 线程更新显示? (不要建议 runOnUiThread,因为我必须在非 UI 线程上运行此代码。)谢谢。
【问题讨论】:
-
如果问题是另一个线程,您的应用程序将崩溃,但 UI 无法从该线程更新或将被忽略。看起来在您的情况下它被忽略了。我也不明白为什么你不能只在更新 UI 的部分上使用 runOnUiThread,其他所有东西都可以在不同的线程上运行
-
@YuriS 更新 UI 的部分也是 CPU 密集型和冻结 UI。
-
你不能从非 UI 线程更新 UI。
标签: java c# android xamarin xamarin.android