← Назад к вопросам

Почему может тормозить отображение текста?

2.0 Middle🔥 181 комментариев
#UI и вёрстка#Производительность и оптимизация

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Проблемы с производительностью при отображении текста в Android

Отображение текста в Android — это комплексная операция, которая может стать "узким местом" по множеству причин. В своей практике я сталкивался с десятками случаев, и вот основные категории проблем, которые нужно проверять в первую очередь.

1. Избыточные операции измерения и отрисовки (Measure/Layout)

Наиболее частая причина — чрезмерно сложная или глубоко вложенная иерархия View. Каждый TextView (и его родители) проходит этапы measure, layout и draw. При вложенности в несколько LinearLayout/RelativeLayout внутри ScrollView сложность растет экспоненциально.

// ПЛОХО: Множество вложенных LayoutManager'ов
<LinearLayout> <!-- 1й уровень -->
    <RelativeLayout> <!-- 2й уровень -->
        <LinearLayout> <!-- 3й уровень -->
            <TextView /> <!-- Целевой View -->
        </LinearLayout>
    </RelativeLayout>
</LinearLayout>

// ЛУЧШЕ: Использовать ConstraintLayout для уплощения иерархии
<androidx.constraintlayout.widget.ConstraintLayout>
    <TextView
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Решение:

  • Использовать ConstraintLayout для минимизации вложенности
  • Включать Merge-теги или использовать ViewStub для необязательных элементов
  • Применять RecyclerView вместо простого ScrollView со множеством дочерних элементов

2. Проблемы со шрифтами и типографикой

Загрузка и рендеринг кастомных шрифтов — дорогостоящая операция.

// ПЛОХО: Установка Typeface в каждом вызове адаптера
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    val typeface = ResourcesCompat.getFont(context, R.font.custom_font)
    holder.textView.typeface = typeface // Загрузка при каждой прокрутке!
}

// ЛУЧШЕ: Кэширование Typeface
object FontCache {
    private val cache = HashMap<String, Typeface>()
    
    fun getFont(context: Context, fontName: String): Typeface {
        return cache.getOrPut(fontName) {
            Typeface.createFromAsset(context.assets, "fonts/$fontName.ttf")
        }
    }
}

Проблемы:

  • Использование setTypeface() в onBindViewHolder() RecyclerView
  • Слишком большие файлы шрифтов (WOFF2 предпочтительнее TTF)
  • Применение Span'ов (SpannableString) с тяжелыми вычислениями

3. Неоптимальное использование Spannable и форматирования

// ПЛОХО: Создание Spannable при каждом обновлении
fun updateText(text: String) {
    val spannable = SpannableString(text)
    spannable.setSpan(ForegroundColorSpan(Color.RED), 0, 5, 0)
    spannable.setSpan(StyleSpan(Typeface.BOLD), 6, 10, 0)
    // ... множество других спанов
    textView.text = spannable
}

// ЛУЧШЕ: Использовать Html или кэширование
fun setupText() {
    // Html.fromHtml кэшируется лучше
    textView.text = HtmlCompat.fromHtml(
        "<b>Жирный</b> и <font color='red'>красный</font> текст",
        HtmlCompat.FROM_HTML_MODE_LEGACY
    )
}

4. Проблемы с аппаратным ускорением и рендерингом

На некоторых устройствах (особенно старых) могут возникать проблемы:

  • Программный рендеринг вместо аппаратного
  • Слишком большая область перерисовки при анимациях
  • Отключенное аппаратное ускорение в манифесте
<!-- Проверьте, не отключено ли ускорение -->
<application
    android:hardwareAccelerated="true"> <!-- Должно быть true -->

5. Проблемы с производительностью самого текста

  • Слишком длинные тексты без разбивки на страницы
  • Отсутствие кэширования измеренной высоты текста
  • Динамическое вычисление размеров текста
// ЛУЧШЕ: Использовать PrecomputedText (API 21+)
val precomputedText = PrecomputedTextCompat.create(
    longText, 
    textView.textMetricsParams
)
textView.setTextFuture(PrecomputedTextCompat.getTextFuture(
    precomputedText,
    textView.textMetricsParams,
    null
))

6. Инструменты для диагностики

Для поиска точной причины используйте:

  1. Profile GPU Rendering в настройках разработчика
  2. Layout Inspector в Android Studio
  3. Systrace для детального анализа каждого этапа рендеринга
  4. Perfetto для современной трассировки

Практический чек-лист для оптимизации

  1. Упростите иерархию View (максимум 10 уровней, лучше меньше)
  2. Кэшируйте шрифты и тяжелые Spannable объекты
  3. Избегайте изменения layout'а во время анимации или прокрутки
  4. Используйте TextView.setMaxLines/Ellipsize для ограничения текста
  5. Применяйте RecyclerView с правильным ViewHolder для списков
  6. Проверьте фон View — полупрозрачность вызывает software rendering
  7. Используйте текст статически там, где это возможно (вместо динамической сборки)

Ключевой показатель: если время отрисовки кадра превышает 16мс (для 60fps), пользователь увидит лаги. Современные устройства с 90-120Hz требуют еще большего быстродействия — до 8-11мс на кадр.

В 80% случаев проблема решается упрощением иерархии View и оптимизацией работы со шрифтами. Остальные 20% требуют глубокого анализа с помощью профилировщиков.

Почему может тормозить отображение текста? | PrepBro