Canvas.drawBitmap() периодически замедляется, вызывая белые вспышки

Работаю над живыми обоями с прокручивающимся фоном.У меня есть два растровых объекта, между которыми я чередую, чтобы сохранить ранее нарисованные пиксели для следующего кадра. Я рисую новую линию в верхней части холста, затем вызываю функцию drawBitmap, чтобы скопировать остальные пиксели на холст.

Я использую объект Runnable для выполнения тяжелой работы. Он выполняет все необходимые операции копирования и вычислений, а затем блокирует холст, вводит синхронный блок на держателе и выполняет единственный вызов Canvas.drawBitmap(bitmap,rect,rect,paint). Время от времени на экране появляется белая вспышка, что, по-видимому, связано с высокой активностью процессора. При использовании traceview я обнаружил, что операция drawBitmap, в частности Canvas.native_drawBitmap(), занимает гораздо больше времени, чем обычно. Обычно это занимает 2-4 мс, но когда я вижу белую вспышку, это может занять от 10 до 100 мс.

private void draw() {
    SurfaceHolder holder = getSurfaceHolder();

    Canvas canvas = null;
    prepareFrame();
    try {
        canvas = holder.lockCanvas();
        synchronized (holder) {
            if (canvas != null) {
                drawFrame(canvas);
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        if (canvas != null)
            holder.unlockCanvasAndPost(canvas);
    }
    afterDrawFrame();
    handler.removeCallbacks(drawRunner);
    if (visible) {
        handler.post(drawRunner);
    }
}

Функция draw()вызывается в run()Runnable.

private void prepareFrame() {
    num++;
    if (num%2 == 0) {
        mainBmp = mainBmp1;
        mainCan.setBitmap(mainBmp1);
        mainCan.drawBitmap(mainBmp2, source, destination, null);
    } else {
        mainBmp = mainBmp2;
        mainCan.setBitmap(mainBmp2);
        mainCan.drawBitmap(mainBmp1, source, destination, null);
    }
}

С помощью функции prepareFrame()я сохраняю предыдущие нарисованные пиксели. Источник, вызываемый Rect, на одну строку меньше полноэкранного размера внизу, а назначение на одну строку короче вверху. Вызовы drawBitmap()в prepareFrame()никогда не превышают 2-4 мс.

private void drawFrame(Canvas can) {
    can.drawBitmap(mainBmp, source, destination,null);
}

Эта единственная операция выполняется на холсте, удерживая замок.

private void afterDrawFrame() {
    ca.calcNextRow();
    mainBmp.setPixels(ca.getRow(), 0, canWidth, 0, 0, canWidth, 1);
}

Затем следующая новая строка пикселей рисуется на одном из моих растровых изображений в памяти.

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

Моя общая скорость отличная.Без прерывистых вспышек работает очень хорошо. У кого-нибудь есть предложения по устранению вспышек?

12
задан rlong 19 June 2012 в 03:20
поделиться