我正在構建一個語法高亮源代碼文件的應用程序。當用戶點擊文件時,我希望他們儘快查看代碼,同時在後臺語法突出顯示代碼(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。 –