1

Je dois laisser l'utilisateur ouvrir un album spécifique de sa galerie et lui laisser faire quelque chose avec des images.Android - Évitez les fuites de mémoire pour les images extraites de la galerie

Afin de récupérer une image d'un album, j'utilise:
Bitmap bitmap = MediaStore.Images.Media.getBitmap(contentResolver, uri).

Tout fonctionne très bien, à l'exception du fait que si l'album contient de nombreuses photos, il finit par trowing un OutOfMemoryException.
maintenant Je sais comment atténuer ce problème sur la base Android guidelines, mais le problème est que je récupérer déjà le Bitmap original avec getBitmap()

Alors, est-il possible de récupérer l'image dans le format de tableau d'octets, ou une entrée format de flux, et le réduire avant de l'affecter en mémoire pour éviter les fuites de mémoire? (de la même manière que les conseils sur les consignes Android)

Répondre

0

Ainsi, ayant une image Uri dans mes mains, je voulais le récupérer est InputStream et réduire l'image avant de l'assigner en mémoire pour éviter OutOfMemoryException

Solution:
Pour récupérer le InputStream d'un Uri, vous devez appeler ceci:

InputStream stream = getContentResolver().openInputStream(uri); 

ensuite suivant les recommandations Android sur loading bitmaps efficiently, il vous suffit d'appeler BitmapFactory.decodeStream(), et passer le BitmapFactory.Options en tant que paramètre.

code source complet:

imageView = (ImageView) findViewById(R.id.imageView); 

Uri uri = Uri.parse("android.resource://com.testcontentproviders/drawable/"+R.drawable.test_image_large); 
Bitmap bitmap=null; 
    try { 
     InputStream stream = getContentResolver().openInputStream(uri); 
     bitmap=decodeSampledBitmapFromStream(stream, 150, 100); 
    } catch (FileNotFoundException e) { 
     e.printStackTrace(); 
    } 

imageView.setImageBitmap(bitmap); 

Méthodes d'aide:

public static Bitmap decodeSampledBitmapFromStream(InputStream stream, 
      int reqWidth, int reqHeight) { 

    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeStream(stream, null, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, 
       reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeStream(stream, null, options); 
} 

public static int calculateInSampleSize(BitmapFactory.Options options, 
      int reqWidth, int reqHeight) { 
    // Raw height and width of image 
    final int height = options.outHeight; 
    final int width = options.outWidth; 
    int inSampleSize = 1; 

    if (height > reqHeight || width > reqWidth) { 
     if (width > height) { 
      inSampleSize = Math.round((float) height/(float) reqHeight); 
     } else { 
      inSampleSize = Math.round((float) width/(float) reqWidth); 
     } 
    } 
    return inSampleSize; 
} 
0

Vous avez déjà identifié une très bonne solution. Si vous voulez passer l'étape de tirer l'image dans un Bitmap via le MediaStore, essayez d'utiliser ImageView.setImageUri().

+0

Salut, merci pour le commentaire. Essayer de passer l'Uri à l'ImageView avant la mise à l'échelle provoque également OutOfMemoryException si l'image est trop grande. Mais vous m'avez ouvert une nouvelle alternative, et sur la base de cette image Uri maintenant je suis capable de récupérer l'InputStream et réduire l'image. Je posterai la solution bientôt. –

Questions connexes