Почему не стоит производить длительных вычислений в методе onDraw у View

Ответ

Длительные вычисления в onDraw() замедляют отрисовку UI, вызывая лаги и пропущенные кадры. onDraw() вызывается часто (при каждой перерисовке View), поэтому он должен быть максимально легковесным.

Проблемы:

  • Блокировка UI-потока → ANR при долгих операциях.
  • Падение FPS из-за перерисовок.

Решение:

  1. Выполняйте тяжелые вычисления заранее (например, в onSizeChanged() или фоновом потоке).
  2. Кешируйте результаты, если они не меняются.
override fun onDraw(canvas: Canvas) {
    // Плохо: вычисление в onDraw
    // val result = heavyCalculation() 

    // Хорошо: используем предвычисленное значение
    canvas.drawText(cachedResult, x, y, paint)
}

Ответ 18+ 🔞

А, ну это же классика, блядь! Слушай, тут такая история, как будто на дворе 2002-й год и ты пытаешься на своём кирпиче с Java ME запустить 3D-шутер. Длительные вычисления прямо в onDraw() — это пиздец какой тормозняк, ядрёна вошь!

Вот представь: твой UI-поток — это такой забеглый официант в переполненном баре. Его задача — быстро разносить пиво (onDraw()), чтобы народ не буянил (пользователь не видел лагов). А ты ему впихиваешь: «А ну-ка, братан, пока разносишь, ещё и квадратные корни в уме посчитай, и JSON распарсь, и в базу сходи». Он, конечно, ебанько, начнёт считать, а все клиенты уже волнение ебать чувствуют — стаканы стучат, FPS падает ниже плинтуса. В итоге овердохуища кадров пропущено, а самый нетерпеливый клиент (система) вызовет ANR (Application Not Responding), что-то вроде «Иди ты нахуй, официант медленный».

В чём, сука, корень зла?

  • UI-поток блокируется. Он должен только рисовать, а не вычислять мировые константы. Заставишь его считать — получишь ANR, красивый диалог, после которого пользователь твоё приложение удалит.
  • FPS летит в тартарары. onDraw() зовут как сумасшедшего — на каждый чих, скролл, анимацию. Если там не легковесная отрисовка, а целая научная диссертация, то про плавность можно забыть. Будет слайд-шоу.

Как не быть распиздяем? Решения:

  1. Делай всё заранее, чувак! Тяжелые штуки считай где угодно, но не в самом onDraw(). Идеальные моменты — onSizeChanged() (когда размеры известны) или, что ещё лучше, в фоновом потоке. Вычислил, сохранил в переменную, и потом только рисуешь готовый результат.
  2. Кешируй, как последний крохобор! Если данные не меняются каждые 10 миллисекунд, зачем их пересчитывать на каждом кадре? Посчитал один раз — и используй, пока не поменяются исходники. Экономия — мать порядка.

Смотри, как это выглядит в коде:

override fun onDraw(canvas: Canvas) {
    // Пиздец как плохо: вычисляем прямо здесь и сейчас.
    // val result = heavyCalculation() // Тут твой UI-поток встанет колом и будет бздеть от натуги.

    // А вот так — красиво и правильно: используем то, что приготовили заранее.
    canvas.drawText(cachedResult, x, y, paint) // Быстро, чётко, без сюрпризов.
}

Запомни: onDraw() — это святое место для быстрой отрисовки. Не превращай его в свалку для своей вычислительной ебли. Сделаешь по-умному — интерфейс будет летать, а пользователь не захочет тебе вилкой в глаз ткнуть за тормоза. Всё гениальное просто.