0

Je rencontre une erreur OutOfMemoryError lorsque j'essaie d'appliquer un fond d'écran à un périphérique. J'utilise un AsyncTask et parfois cela fonctionne bien, mais parfois cela arrive.Erreur OutOfMemory lors de l'application du fond d'écran

Quelqu'un peut-il m'aider à l'optimiser encore plus? Merci d'avance.

Code AsyncTask:

public class ApplyWallpaper extends AsyncTask<Void, String, Boolean> { 
    private Context context; 
    private Activity activity; 
    private MaterialDialog dialog; 
    private Bitmap resource; 
    private View layout; 
    private boolean isPicker; 
    private Snackbar snackbar; 

    public ApplyWallpaper(Context context, MaterialDialog dialog, Bitmap resource, Boolean isPicker, View layout) { 
     this.activity = (Activity) context; 
     this.context = context; 
     this.dialog = dialog; 
     this.resource = resource; 
     this.isPicker = isPicker; 
     this.layout = layout; 
    } 

    @Override 
    protected Boolean doInBackground(Void... params) { 
     WallpaperManager wm = WallpaperManager.getInstance(context); 
     Boolean worked; 
     try { 
      wm.setBitmap(scaleToActualAspectRatio(resource)); 
      worked = true; 
     } catch (IOException e2) { 
      worked = false; 
     } 
     return worked; 
    } 

    @Override 
    protected void onPostExecute(Boolean worked) { 
     if (worked) { 
      dialog.dismiss(); 
      Util.showSimpleSnackbar(layout, 
        context.getString(R.string.set_as_wall_done), 1); 
     } else { 
      String retry = context.getResources().getString(R.string.retry); 
      snackbar = Snackbar 
        .make(layout, R.string.error, Snackbar.LENGTH_INDEFINITE) 
        .setAction(retry.toUpperCase(), new View.OnClickListener() { 
         @Override 
         public void onClick(View view) { 
          new ApplyWallpaper(context, dialog, resource, isPicker, layout); 
         } 
        }); 
      snackbar.setActionTextColor(context.getResources().getColor(R.color.accent)); 
      snackbar.show(); 
     } 
     if (isPicker) { 
      activity.finish(); 
     } 

    } 

    public Bitmap scaleToActualAspectRatio(Bitmap bitmap) { 
     if (bitmap != null) { 
      boolean flag = true; 
      int deviceWidth = activity.getWindowManager().getDefaultDisplay() 
        .getWidth(); 
      int deviceHeight = activity.getWindowManager().getDefaultDisplay() 
        .getHeight(); 
      int bitmapHeight = bitmap.getHeight(); 
      int bitmapWidth = bitmap.getWidth(); 
      if (bitmapWidth > deviceWidth) { 
       flag = false; 
       int scaledHeight = deviceHeight; 
       int scaledWidth = (scaledHeight * bitmapWidth)/bitmapHeight; 
       try { 
        if (scaledHeight > deviceHeight) 
         scaledHeight = deviceHeight; 
        bitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, 
          scaledHeight, true); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
      if (flag) { 
       if (bitmapHeight > deviceHeight) { 
        int scaledHeight = deviceHeight; 
        int scaledWidth = (scaledHeight * bitmapWidth) 
          /bitmapHeight; 
        try { 
         if (scaledWidth > deviceWidth) 
          scaledWidth = deviceWidth; 
         bitmap = Bitmap.createScaledBitmap(bitmap, scaledWidth, 
           scaledHeight, true); 
        } catch (Exception e) { 
         e.printStackTrace(); 
        } 
       } 
      } 
     } 
     return bitmap; 
    } 

} 

ressource papier peint est chargé de:

Glide.with(context) 
.load(linkForWallpaper) 
.asBitmap() 
.into(new SimpleTarget<Bitmap>() { 
    @Override 
    public void onResourceReady(final Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) { 
     if (resource != null) { 
      new ApplyWallpaper(context, dialogApply, resource, 
        false, layout, fab).execute(); 
     } 
    } 
}); 
+1

D'où vient la ressource Bitmap? –

+0

@tinysunlight Question éditée –

+0

Utilisez les outils de surveillance de l'application Android Studio pour analyser la mémoire dans le tas que votre application utilise lorsque vous appliquez le fond d'écran, et trouvez les objets qui remplissent le tas –

Répondre

0

Ajouter android:largeHeap="true" dans votre balise d'application dans le fichier Manifest

<application 
     android:name=".MyApplication" 
     android:largeHeap="true" 
     ........ > 
</application> 

Il augmentera une mémoire allouée à votre application

Quel document officiel dit:

android: largeHeap

Que les processus de votre application doivent être créés avec un grand tas Dalvik. Cela s'applique à tous les processus créés pour l'application . Il s'applique uniquement à la première application chargée dans un processus ; Si vous utilisez un ID utilisateur partagé pour autoriser plusieurs applications à utiliser un processus, ils doivent tous utiliser cette option de manière cohérente ou présenter des résultats imprévisibles. La plupart des applications doivent ne pas avoir besoin de cela et devraient plutôt se concentrer sur la réduction de leur utilisation de la mémoire globale pour des performances améliorées. L'activation de cette option ne garantit pas non plus une augmentation fixe de la mémoire disponible, car certains périphériques sont limités par la mémoire totale disponible.

Pour interroger la taille de la mémoire disponible lors de l'exécution, utilisez les méthodes getMemoryClass() ou getLargeMemoryClass().

0

Quelle est la taille d'origine du bitmap que vous chargez? J'ai rencontré le même problème moi-même et la seule façon de le résoudre est de le redimensionner d'abord à une taille beaucoup plus faible qu'à l'origine, puis de le charger (j'ai utilisé picasso) pour l'agrandir.

-1

Vous décodés et bitmap tout en analysez une fois à l'échelle ...() méthode, qui est extrêmement tasking, mémoire sage, vous attrapez cela et faire à nouveau sans appeler cela et il partirait avec un manque évident de mise à l'échelle

La clé de la mise à l'échelle avec un bitmap énorme est de faire manuellement l'analyse et la mise à l'échelle et probablement avant de le définir dans le Gestionnaire de papier peint. Le travail fragmentaire est la toile. android.graphics.Canvas si je me souviens bien.