исправлений
Описание
fun openFile(fileContent: String) {
// 1. Сбрасываем курсор в начало перед заменой текста
Selection.removeSelection(binding.codeEditor.text)
// 2. Устанавливаем новый текст
binding.codeEditor.setText(fileContent)
// 3. Безопасно ставим курсор в начало (индекс 0, 0)
val editable = binding.codeEditor.text
if (editable != null && editable.isNotEmpty()) {
Selection.setSelection(editable, 0, 0)
}
}
private var syntaxHighlightJob: Job? = null
fun applySyntaxHighlighting(text: Editable) {
// Отменяем предыдущую подсветку, если текст изменился
syntaxHighlightJob?.cancel()
syntaxHighlightJob = CoroutineScope(Dispatchers.Default).launch {
val snapshotText = text.toString()
val spans = parseTokens(snapshotText) // Ваша логика разбора кода
withContext(Dispatchers.Main) {
// Проверяем, что текст не успел измениться за время парсинга
if (text.length == snapshotText.length) {
spans.forEach { token ->
text.safeSetSpan(token.createSpan(), token.start, token.end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
}
}
}
}
fun SpannableStringBuilder.safeSetSpan(what: Any, start: Int, end: Int, flags: Int) {
val len = this.length
// Проверяем, что начальный и конечный индексы находятся внутри текущего текста
if (start in 0..len && end in 0..len && start <= end) {
try {
this.setSpan(what, start, end, flags)
} catch (e: IndexOutOfBoundsException) {
// Защита на случай гонки потоков (Race Condition)
e.printStackTrace()
}
}
}
fun safeSetSelection(text: Spannable, start: Int, end: Int) {
val len = text.length
if (len == 0) return
// Ограничиваем индексы строго в диапазоне от 0 до длины текста
val safeStart = start.coerceIn(0, len)
val safeEnd = end.coerceIn(0, len)
// В Android start не должен быть больше end при установке выделения
if (safeStart <= safeEnd) {
Selection.setSelection(text, safeStart, safeEnd)
} else {
Selection.setSelection(text, safeEnd, safeStart)
}
}
код на исправлении краша
Обсуждение · 1
Чзх
Оставить ответ
Установите клиент для Android — обсуждение, установка плагинов и ответы живут там.