LockCanvas() очень медленно

Тестирование моей игры на более медленном устройстве (Orange San Francisco aka ZTE Blade), и я получаю ужасную частоту кадров.

Я ввел код отладки в цикл рисования и обнаружил, что следующая строка занимает более 100 мс:

c = mSurfaceHolder.lockCanvas();

Кто-нибудь еще видел это поведение? Я временно заменил viewview, расширив View и внедряя onDraw(), и у меня получилось намного лучшее соотношение частоты кадров.

Несмотря на то, что в целом, на моем HTC Desire работает намного более поверхностный вид. Я подозрюю, это может быть проблема Android 2.1. Я предполагаю, что укореняю телефон и обновляю его до версии 2.2, если это возможно, но мне нужно, чтобы устройство работало на 2.1, чтобы оно могло быть контрпродуктивным в конечном итоге.

** обновление **

Я работаю над этим еще и обнаружил еще несколько загадочных аспектов.

Я укоренил телефон и установил 2.2, и проблема все еще происходит. Когда приложение запускается первым, lockCanvas работает как ожидалось (0-1 мс). Затем в какой-то момент во время моей инициализации lockCanvas внезапно начинает принимать около 100 мс.

Возможно, стоит отметить, что я загружаю свои активы в задачу Async, чтобы отображать экран загрузки.

Несмотря на все мои усилия, чтобы определить, что программа действительно делает, когда произошла медлительность, я не смог этого сделать. Фактически, когда я запускаю его в режиме отладки и на одном шаге, он работает быстро!

Теперь я обнаружил, что если добавить задержку в конструктор моего SurfaceView (около 10 секунд), то медлительность не возникает, и все работает нормально.

Однако, если вы нажмете "Домой", а затем вернитесь назад, медленность вернется.

Я почти в конце моего троса по этой глупой нелогичной проблеме! У меня есть ум, чтобы решить проблему, связанную с устройством.

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

Меня бы интересовали теории.

Ответ 1

О lockCanvas() из документов:

Если вы вызываете это повторно, когда Поверхность не готова (до Callback.surfaceCreated или after Callback.surfaceDestroyed), ваши вызовы будет сдерживаться медленным темпом в чтобы избежать использования процессора.

Возможно ли, что ваш цикл рисования инициирован слишком рано для некоторых устройств? Я думаю, что это проблема, поскольку вы написали:

Теперь я обнаружил, что если добавить задержку в конструкторе моего SurfaceView (около 10 секунд), медленность не происходит, и все работает нормально.

Ответ 2

Итак, возможно, мы могли бы использовать файл holder.isCreating() для проверки состояния? этот метод вернет true, если холст все еще создает.

Что-то вроде while (holder.isCreating()) {} может = holder.lockCanvas();

Но я немного запутался. Поскольку я знаю, что colbeck вызывается, когда создается поверхностное представление. Мы должны реализовать интерфейс SurfaceHolder.Callback. А когда поверхность создается методом обратного вызова будет вызываться public void surfaceCreated (держатель SurfaceHolder) {}. Из метода surfaceCreated я запускаю поток gameloop.

Ответ 3

Недавно я обнаружил, что если большие растровые изображения используются для рисования на холсте и, эти растровые изображения сохраняются в классе активности - команда "_surfaceHolder.lockCanvas()" занимает очень много времени (около 70 мс в зависимости от устройства). ОДНАКО, перемещая это хранилище битмапов в другой класс (в другом файле, скажем, MY_DATA), и активность имеет только ссылку на этот новый класс - решает проблему.

У меня нет объяснений этому явлению.

Ответ 4

Я столкнулся с той же загадочной проблемой с рисунком Canvas, но решил ее, изменив рисунок Canvas на рисунок на SurfaceView. Но теперь у меня постоянно медленный вызов lockCanvas(). Вот мои результаты наблюдения. Проблема присутствует только на некоторых устройствах:

  • Galaxy Note 3 n900: есть проблемы.
  • Galaxy Note 3 n9005: есть проблемы.
  • Galaxy S4 i9505: есть проблемы
  • Galaxy Gio: проблем нет
  • LG G2 D802: есть проблемы
  • Galaxy S2 i9100: проблем нет

Я временно заменил viewview, расширив View и внедряя onDraw(), и у меня получилась намного лучшая частота кадров

Я также заметил, что телефоны Samsung используют GLES20Canvas вместо обычного Canvas с рисунком onDraw(), в результате, лучшую производительность.