2011-04-02 4 views
12

Tengo un mapa personalizado sin conexión implementado dibujando mosaicos de mapa de bits en el lienzo. Estoy tratando de eliminar las creaciones de objeto para reducir las carreras de GC y, por lo tanto, hacer que el desplazamiento del mapa sea más suave. Veo en Allocation Tracker que BitmapFactory.decodeFile (...) siempre crea el objeto byte [16400]. Pensé que el establecimiento de campo inTempStorage de BitmapFactory.Options cambiaría eso:campo BitmapFactory.Options.inTempStorage

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); 

Pero incluso con este código Todavía veo decodeFile crear el [] matriz de bytes. ¿Entonces, cuál es el problema?

Respuesta

16

En resumen, el problema es que cuando se utiliza BitmapFactory.decodeFile(String, Options) continuación Android asignará un 16 kB BufferedInputStream, independientemente options.inTempStorage.

Para ser más elaborado: BitmapFactory.decodeFile(String, Options) es un contenedor alrededor de BitmapFactory.decodeStream(InputStream, Rect, Options) que usa un FileInputStream. En la implementación de BitmapFactory.decodeStream(InputStream, Rect, Options), hay this 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); 
    } 

    // ... 
} 

Desde FileInputStream 's markSupported() vuelve false, eso significa que, independientemente de options.inTempStorage, un BufferedInputStream con un buffer de 16 kB se creará para usted si utiliza BitmapFactory.decodeFile(String, Options).

Para evitar esta asignación de 16 kB, usted podría tratar de usar BitmapFactory.decodeStream(InputStream, Rect, Options) directamente con un InputStreammarkSupported() para el que vuelve true.

puedo pensar en dos alternativas que podrían ser vale la pena analizar:

  1. Use su propio BufferedInputStream con un búfer menor
  2. Uso AssetManager.AssetInputStream tal como lo devuelve AssetManager.open(...) (véase mi respuesta here sobre cómo usarlo) Es markSupported() devuelve true.

La primera alternativa puede no ser de mucha ayuda, aún tendrá una matriz de bytes [] asignada, pero al menos está bajo su control. La segunda opción podría ser la más fructífera, si sus circunstancias le permiten utilizar este enfoque.