Wie zu lösen java.lang.OutOfMemoryError Probleme in Android

Obwohl ich sehr kleine Größe Bild in ziehbare Ordner habe, bekomme ich diese Fehler von Benutzern. Und ich benutze keine Bitmap-Funktion im Code. Zumindest absichtlich 🙂

java.lang.OutOfMemoryError at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:683) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:513) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:889) at android.content.res.Resources.loadDrawable(Resources.java:3436) at android.content.res.Resources.getDrawable(Resources.java:1909) at android.view.View.setBackgroundResource(View.java:16251) at com.autkusoytas.bilbakalim.SoruEkrani.cevapSecimi(SoruEkrani.java:666) at com.autkusoytas.bilbakalim.SoruEkrani$9$1.run(SoruEkrani.java:862) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:146) at android.app.ActivityThread.main(ActivityThread.java:5602) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1283) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099) at dalvik.system.NativeStart.main(Native Method) 

Nach diesem StackTrace bin ich gettin diesen Fehler an dieser Zeile ('tv' ist ein textView):

 tv.setBackgroundResource(R.drawable.yanlis); 

Was ist das Problem? Wenn du irgendwelche anderen Informationen über Code brauchst, kann ich es hinzufügen. Vielen Dank!

  • JSCallback Server Closed: Stoppen von Rückrufen
  • Android: Ergebnis vom Callback erhalten (Networking KOUSH ION)
  • Spotify Login Fehler INVALID_CLIENT: Ungültige Redirect URI Android
  • Wie man OAuth-URL-Rückrufe mit Absichtsfilter verarbeitet, wenn die Authentifizierung mit Webview erfolgt?
  • Verwenden von ResultReceiver in Android
  • App-Crashing bei Verwendung von Retrofit-Rückruf im Debug-Modus
  • Android - Alles ähnlich wie das iPhone SDK Delegate Callbacks?
  • Android Dev - Rückruf-URL funktioniert nicht ... (0_o)
  • 3 Solutions collect form web for “Wie zu lösen java.lang.OutOfMemoryError Probleme in Android”

    Sie können die Haufengröße nicht dynamisch erhöhen, aber Sie können verlangen, mehr zu verwenden, indem Sie verwenden.

    Android: largeHeap = "wahr"

    In der manifest.xml , kannst du in deinem Manifest diese Zeilen hinzufügen, die es für einige Situationen arbeitet.

     <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:largeHeap="true" android:supportsRtl="true" android:theme="@style/AppTheme"> 

    Ob die Prozesse Ihrer Anwendung mit einem großen Dalvik-Heap erstellt werden sollen. Dies gilt für alle für die Anwendung erstellten Prozesse. Es gilt nur für die erste Anwendung, die in einen Prozess geladen wird; Wenn Sie eine freigegebene Benutzer-ID verwenden, um mehrere Anwendungen zu erlauben, einen Prozess zu verwenden, müssen sie diese Option konsequent verwenden oder sie haben unvorhersehbare Ergebnisse. Die meisten Apps sollten das nicht brauchen und sollten sich stattdessen darauf konzentrieren, ihren gesamten Speicherverbrauch für eine verbesserte Leistung zu reduzieren. Dies ermöglicht auch nicht eine feste Erhöhung des verfügbaren Speichers, da einige Geräte durch ihren gesamten verfügbaren Speicherplatz eingeschränkt sind.


    Um die verfügbare Speichergröße zur Laufzeit abzufragen, verwenden Sie die Methoden getMemoryClass() oder getLargeMemoryClass() .

    Wenn immer noch Problem, dann sollte dies auch funktionieren

      BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 8; mBitmapInsurance = BitmapFactory.decodeFile(mCurrentPhotoPath,options); 

    Wenn Sie auf einen Wert> 1 setzen, fordert der Decoder auf, das Originalbild abzusammeln und ein kleineres Bild zurückzusetzen, um Speicher zu speichern.

    Dies ist die optimale Nutzung von BitmapFactory.Options.inSampleSize in Bezug auf die Geschwindigkeit der Anzeige des Bildes. Die Dokumentation erwähnt mit Werten, die eine Macht von 2 sind, also arbeite ich mit 2, 4, 8, 16 etc.

    Lets immer tiefer zu Image Sampling:

    Zum Beispiel ist es nicht wert, ein 1024×768 Pixel-Bild in den Speicher zu laden, wenn es schließlich in einer 128×128 Pixel-Miniaturansicht in einem ImageView .

    Um dem Decoder zu signalisieren, das Bild zu unterteilen, laden Sie eine kleinere Version in den Speicher, setzen Sie inSampleSize auf true in Ihrem BitmapFactory.Options Objekt. Beispielsweise erzeugt ein Bild mit einer Auflösung von 2100 x 1500 Pixeln, das mit einem inSampleSize von 4 decodiert wird, eine Bitmap von etwa 512×384. Das Laden in den Speicher verwendet 0.75MB anstatt 12MB für das Vollbild (unter der Annahme einer Bitmap-Konfiguration von ARGB_8888 ). Hier ist eine Methode, um einen Stichprobengrößenwert zu berechnen, der eine Stärke von zwei ist, die auf einer Zielbreite und -höhe basiert:

     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) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; } 

    Anmerkung : Eine Leistung von zwei Werten wird berechnet, weil der Decoder einen Endwert verwendet, indem er auf die nächstgelegene Leistung von zwei, wie in der inSampleSize Dokumentation, inSampleSize .

    Um diese Methode zu verwenden, entschlüsseln inJustDecodeBounds zuerst mit inJustDecodeBounds auf true , übergeben Sie die Optionen durch und dann decodieren Sie erneut mit dem neuen inSampleSize Wert und inJustDecodeBounds auf false :

     public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); } 

    Diese Methode macht es einfach, eine Bitmap von beliebig großer Größe in eine ImageView zu ImageView , die eine 100×100 Pixel-Miniaturansicht anzeigt, wie im folgenden Beispielcode gezeigt:

     mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100)); 

    Sie können einen ähnlichen Prozess verfolgen, um Bitmaps aus anderen Quellen zu dekodieren, indem Sie die entsprechende BitmapFactory.decode* -Methode nach Bedarf BitmapFactory.decode* .


    Ich fand diesen Code auch interessant:

     private Bitmap getBitmap(String path) { Uri uri = getImageUri(path); InputStream in = null; try { final int IMAGE_MAX_SIZE = 1200000; // 1.2MP in = mContentResolver.openInputStream(uri); // Decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; BitmapFactory.decodeStream(in, null, o); in.close(); int scale = 1; while ((o.outWidth * o.outHeight) * (1 / Math.pow(scale, 2)) > IMAGE_MAX_SIZE) { scale++; } Log.d(TAG, "scale = " + scale + ", orig-width: " + o.outWidth + ", orig-height: " + o.outHeight); Bitmap bitmap = null; in = mContentResolver.openInputStream(uri); if (scale > 1) { scale--; // scale to max possible inSampleSize that still yields an image // larger than target o = new BitmapFactory.Options(); o.inSampleSize = scale; bitmap = BitmapFactory.decodeStream(in, null, o); // resize to desired dimensions int height = bitmap.getHeight(); int width = bitmap.getWidth(); Log.d(TAG, "1th scale operation dimenions - width: " + width + ", height: " + height); double y = Math.sqrt(IMAGE_MAX_SIZE / (((double) width) / height)); double x = (y / height) * width; Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, (int) x, (int) y, true); bitmap.recycle(); bitmap = scaledBitmap; System.gc(); } else { bitmap = BitmapFactory.decodeStream(in); } in.close(); Log.d(TAG, "bitmap size - width: " +bitmap.getWidth() + ", height: " + bitmap.getHeight()); return bitmap; } catch (IOException e) { Log.e(TAG, e.getMessage(),e); return null; } 

    So verwalten Sie den Speicher Ihrer App: Link


    Es ist nicht eine gute Idee, android:largeHeap="true" zu benutzen android:largeHeap="true" hier ist der Auszug aus Google, der es erklärt,

    Allerdings ist die Fähigkeit, einen großen Heap anzufragen, nur für einen kleinen Satz von Apps gedacht, die die Notwendigkeit, mehr RAM zu verbrauchen (wie eine große Fotobearbeitungs-App) zu rechtfertigen. Niemals einen großen Heap anfordern, nur weil du kein Gedächtnis hast und du eine schnelle Lösung benötigst – du solltest es nur benutzen, wenn du genau weißt, wo all dein Gedächtnis zugewiesen ist und warum es behalten werden muss. Doch selbst wenn Sie zuversichtlich sind, dass Ihre App den großen Haufen rechtfertigen kann, sollten Sie es vermeiden, es zu einem beliebigen Ausmaß zu geben. Die Verwendung des zusätzlichen Speichers wird zunehmend zum Nachteil der gesamten Benutzererfahrung sein, da die Garbage Collection länger dauert und die Systemleistung bei der Taskwechsel oder bei der Ausführung anderer gemeinsamer Operationen langsamer sein kann.

    Nach der Arbeit excrutiatingly mit out of memory errors würde ich sagen, das Hinzufügen dieses zu dem manifest zu vermeiden, das oom Problem ist nicht eine Sünde


    Überprüfen des App-Verhaltens auf der Android Runtime (ART)

    Die Android-Laufzeit (ART) ist die Standardlaufzeit für Geräte mit Android 5.0 (API Level 21) und höher. Diese Laufzeit bietet eine Reihe von Funktionen, die die Leistung und die Laufruhe der Android-Plattform und Apps verbessern. Hier finden Sie weitere Informationen über die neuen Features von ART in der Einführung von ART .

    Doch einige Techniken, die auf Dalvik arbeiten, arbeiten nicht an ART. In diesem Dokument können Sie wissen, was Sie beachten möchten, wenn Sie eine vorhandene App migrieren möchten, um mit ART kompatibel zu sein. Die meisten Apps sollten nur bei der Ausführung mit ART arbeiten.


    Adressierung von Garbage Collection (GC) Issues

    Unter Dalvik finden apps häufig es sinnvoll, explizit System.gc () aufzufordern, um Garbage Collection (GC) aufzufordern. Dies sollte bei ART weit weniger notwendig sein, besonders wenn Sie Garbage Collection aufrufen, um GC_FOR_ALLOC-Typ Vorkommen zu verhindern oder um die Fragmentierung zu reduzieren. Sie können überprüfen, welche Laufzeit verwendet wird, indem Sie System.getProperty ("java.vm.version") aufrufen. Wenn ART in Gebrauch ist, ist der Wert der Eigenschaft "2.0.0" oder höher.

    Darüber hinaus ist ein kompaktes Garbage Collector in der Entwicklung im Android Open-Source-Projekt (AOSP) zur Verbesserung der Speicherverwaltung. Aus diesem Grund sollten Sie vermeiden, Techniken zu verwenden, die mit dem Komprimieren von GC nicht kompatibel sind (z. B. Speichern von Zeigern auf Objektinstanzdaten). Dies ist besonders wichtig für Apps, die das Java Native Interface (JNI) nutzen. Weitere Informationen finden Sie unter Verhindern von JNI-Problemen.


    Verhindern von JNI-Problemen

    ART's JNI ist etwas strenger als Dalviks. Es ist eine besonders gute Idee, den CheckJNI-Modus zu verwenden, um gemeinsame Probleme zu lösen. Wenn Ihre App den C / C ++ – Code verwendet, sollten Sie den folgenden Artikel lesen:


    Außerdem können Sie nativen Speicher ( NDK & JNI ) verwenden, so dass Sie tatsächlich die Haufengröße einschränken.

    Hier sind einige Beiträge gemacht:

    Und hier ist eine Bibliothek dafür gemacht:

    Sie sollten einen LRU-Cache-Manager beim Umgang mit Bitmap implementieren

    http://developer.android.com/reference/android/util/LruCache.html http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html Wann sollte ich eine Bitmap mit LRUCache recyceln?

    ODER

    Verwenden Sie eine Tierbibliothek wie Universal Image Loader:

    https://github.com/nostra13/Android-Universal-Image-Loader

    EDIT:

    Jetzt beim Umgang mit Bildern und die meiste Zeit mit Bitmap verwende ich Glide, mit der du ein Gleitmodul und einen LRUCache konfigurieren kannst

    https://github.com/bumptech/glide

    Ich sehe nur zwei Möglichkeiten:

    1. Sie haben Speicherverluste in Ihrer Anwendung.
    2. Geräte haben nicht genügend Speicher, wenn Sie Ihre Anwendung ausführen.
    Das Android ist ein Google Android Fan-Website, Alles über Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.