Плохая производительность при непрерывном рисовании в CustomView

Случай использования:

Мне нужно нарисовать сотни строк и немного текста на мой взгляд. Мне нужно дать эффект прокрутки, для которого я захватываю событие ACTION_MOVE и перерисовываю все строки с обновленными точками. Чтобы получить результат желания, я попытался с разными подходами, но никто не работает по назначению.

Подход 1

Я создал собственный класс, который расширяет View . Все чертежи и вычисления выполняются непосредственно в моем onDraw() . Поскольку в onDraw() выполняется так много операций, производительность приложения очень плохая. Я даже проверил производительность, используя рендеринг профиля GPU, и я вижу, что линии очень высокие.

Подход 2

Я создал растровое изображение и после рисования всех строк на моем растровом изображении в другом потоке я использовал postInvalidate() для рисования растрового изображения в onDraw()

 mBufferedBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); mBufferedBitmap.eraseColor(Color.TRANSPARENT); Canvas mBufferedCanvas = new Canvas(mBufferedBitmap); drawLines(mBufferedCanvas) postInvalidate(); 

Так как я стираю все предыдущий рисунок на растровом изображении и рисую новые строки с обновленными точками, на экране появляется мерцание.

Подход 3

Я попытался расширить свой собственный класс до SurfaceView и выполнить все операции над объектом canvas в другом потоке. Но поскольку SurfaceView использует процессор для операций рисования, производительность будет низкой в ​​мобильных телефонах с низкой конфигурацией.

Может ли кто-нибудь вести меня, как достичь этой задачи с лучшей производительностью?

Для достижения хорошей производительности можно использовать свой подход 1 .

Пример, который звучит близко к вашему прецеденту (линии рисования, небольшой текст и наличие этого обновления для движения жестов) – MPAndroidChart . Это библиотека с открытым исходным кодом, которая обеспечивает высокую производительность (см. Следующее сравнение, если вы хотите получить статистику)

Классы для проверки являются классами Renderer как они содержат код, нарисованный в onDraw(Canvas c) подтипов диаграммы. Вы можете увидеть некоторые из трюков, используемых для достижения высокой производительности:

  1. Не выделяйте в цикле рендеринга. Вместо этого выделяйте вне цикла и повторно использовать / перерабатывать переменные. См. LineChartRenderer 199
  2. Используйте буферизацию. Например, в MPAndroidChart точки для четырех углов баров на гистограмме буферизуются, и буферный массив повторно используется. См. Класс BarBuffer .
  3. Используйте собственные функции рисования холста ( drawPath , drawLine и т. Д.).

Подход 2 – лучший. Если вы видите мерцание, это означает, что растровое изображение рисуется на экране после того, как вы его удалите, и прежде чем рисовать все линии. Если это так, используйте другое растровое изображение и выполните двойную буферизацию:

ScreenBitmap – это то, что нарисовано для экрана. OffScreenBitmap используется для рисования в фоновом режиме.

Нарисуйте все ваши строки и текст на OffScreenBitmap, и как только закончите, скопируйте его в ScreenBitmap. В onDraw нарисуйте ScreenBitmap.

Создавайте эти растровые изображения один раз (обычно в onSizeChanged), так что в onDraw нет alloocation