12 Stimmen

Feld BitmapFactory.Options.inTempStorage

Ich habe eine benutzerdefinierte Offline-Karte durch Zeichnen von Bitmap-Kacheln auf Canvas implementiert. Ich versuche, die Objekterstellung zu eliminieren, um die GC-Läufe zu reduzieren und somit das Scrollen der Karte flüssiger zu gestalten. Im Allocation Tracker sehe ich, dass BitmapFactory.decodeFile(...) immer ein byte[16400] Objekt erzeugt. Ich dachte, dass die Einstellung des Feldes inTempStorage in BitmapFactory.Options dies ändern würde:

byte[] buffer = new byte[16*1024];
// ...
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Config.RGB_565;
options.inTempStorage = buffer;
Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath(), options);

Aber auch mit diesem Code sehe ich immer noch decodeFile erstellen die byte[] Array. Wo liegt also das Problem?

17voto

Martin Nordholts Punkte 10238

Kurz gesagt, das Problem ist, dass Sie bei der Verwendung von BitmapFactory.decodeFile(String, Options) dann wird Android einen 16 kB BufferedInputStream unabhängig von options.inTempStorage .

Um es genauer zu formulieren: BitmapFactory.decodeFile(String, Options) ist ein Wrapper um BitmapFactory.decodeStream(InputStream, Rect, Options) die eine FileInputStream . Bei der Umsetzung von BitmapFactory.decodeStream(InputStream, Rect, Options) gibt es dieser Code :

public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
    // ...

    // we need mark/reset to work properly
    if (!is.markSupported()) {
        is = new BufferedInputStream(is, 16 * 1024);
    }

    // ...
}

Seit FileInputStream 's markSupported() gibt zurück. false das bedeutet, dass unabhängig von options.inTempStorage , a BufferedInputStream mit einem 16 kB großen Puffer wird für Sie erstellt, wenn Sie BitmapFactory.decodeFile(String, Options) .

Um diese 16 kB Zuweisung zu vermeiden, könnten Sie versuchen, die BitmapFactory.decodeStream(InputStream, Rect, Options) direkt mit einer InputStream bei denen markSupported() gibt zurück. true .

Mir fallen zwei Alternativen ein, die man in Betracht ziehen könnte:

  1. Verwenden Sie Ihr eigenes BufferedInputStream mit einem kleineren Puffer
  2. 使用方法 AssetManager.AssetInputStream wie zurückgegeben von AssetManager.open(...) (siehe meine Antwort aquí wie sie zu verwenden ist). Sein markSupported() gibt zurück. true .

Die erste Alternative ist vielleicht nicht sehr hilfreich, da Sie immer noch ein Byte[]-Array zugewiesen bekommen, aber zumindest haben Sie die Kontrolle darüber. Die zweite Option könnte sich als die fruchtbarste erweisen, wenn Ihre Umstände es erlauben, diesen Ansatz zu verwenden.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X