我正在构建一个语法高亮源代码文件的应用程序。当用户点击文件时,我希望他们尽快查看代码,同时在后台语法突出显示代码(CPU密集型)。这是我写的代码(它使用C#/ Xamarin,但Java的开发者可以用一些精力翻译本):如何使SpannableStringBuilder.setSpan更新非UI线程上的显示?
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);
}
}
的重要组成部分,是我第一次打电话SetText()
与ColoredText
,这是一个自定义类型只是包装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。 –