Подтвердить что ты не робот

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

4b9b3361

Ответ 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) имеет несколько буферов: один используется приложениями для рисования, а один используется системой для рендеринга, а иногда есть третий, если приложение не может закончить рисование своевременно. Невозможно отключить его, и вы не захотите. И именно по этой причине вы получаете разный холст, когда блокируете, как вы уже заметили.