LockCanvas() возвращает различные холсты
Пытаемся нарисовать что-то каждый мс на одном холсте. Я имею в виду только добавление деталей в холст, а не перерисовку всего кадра. Таким образом, этот код дает мне три разных полотна. В-третьих, сначала сначала. Почему?
public void run() {
this.run = true;
Canvas canvas = null;
while (run) {
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (this.surfaceHolder) {
Thread.sleep(delay);
draw(new Img(canvas, size));
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (canvas != null) {
this.surfaceHolder.unlockCanvasAndPost(canvas);
}
}
synchronized (this) {
if (wait) {
try {
wait();
} catch (Exception e) {}
}
}
}
}
Если это андроидная тройная буферизация - как отключить ее или сделать что-то с ней?
Android 4.2.1
Ответы
Ответ 1
-
Я бы рекомендовал не называть логическое поле "run" в реализации Runnable (в котором метод возвращает void). Даже если проблемы не выходят из конфликта, это запутывает. Может быть, "работает", или что-то (что-то), будет иметь больше смысла - проще отлаживать.
-
Не используйте Object.wait при многопоточности. Это не всегда (как правило, не будет) действовать так, как вы могли ожидать.
-
Скорее всего, вы получаете несколько экземпляров вашего члена Canvas, потому что где-то (возможно, в каркасе Android или, может быть, в вашем коде... трудно сказать), "new Canvas (args)" вызывается во время то, что вы считаете своим единственным экземпляром Canvas, находится в другом потоке. Хотя у вас есть только одна ссылка, может быть создано несколько экземпляров.
-
Я бы не рекомендовал использовать синхронизированный (независимо), если вы не уверены, что вам нужно это сделать.
-
Повесьте там. Эта проблема очень сбивает с толку - я проработал ее последним Spring, и это было нелегко или весело.
Надеюсь, что какое-либо из вышеперечисленных помогает в некотором роде.
-Brandon
Ответ 2
Если вам нравится сохранять предыдущий розыгрыш, вы должны нарисовать их на экранном холсте и нарисовать их на холсте, который вы получили на холсте блокировки.
Код puesd для иллюстрации идеи:
Bitmap offScreenBitmap = Bitmap.createBitmap(100,200,Bitmap.ARGB_8888);
Canvas offScreenCanvas = new Canvas(offScreenBitmap);
onScreenCanvas = this.surfaceHolder.lockCanvas();
//always draw to te offScreenCanvas
offScreenCanvas.drawXxxx
//copy the data to on-screen canvas you got from the lock
onScreenCanvas.drawBitmap(offScreenBitmap);
unlockAndPost(onScreenCanvas)
Это должно выполнить вашу задачу. Правильно?
Затем немного под капотом:
Да, андроид (поверхность IS A view) имеет несколько буферов: один используется приложениями для рисования, а один используется системой для рендеринга, а иногда есть третий, если приложение не может закончить рисование своевременно. Невозможно отключить его, и вы не захотите. И именно по этой причине вы получаете разный холст, когда блокируете, как вы уже заметили.