Java Referenzen von Bildobjekten löschen

alex_00

Cadet 2nd Year
Registriert
Dez. 2016
Beiträge
31
Hallo,

ich benutze Android Studio (Java) und habe dort begonnen, eine App zu programmieren. Die App besteht hauptsächlich aus Bildern. Öffne ich nun manche Layouts, so stürzt die App ab. Ich habe mir sagen lassen, dass ich die Referenzen der Bildobjekte löschen soll, damit der Garbage Collector die Objekte löschen kann und der Arbeitsspeicher der App nicht voll wird. Allerdings weiß ich nicht, wie ich von Bildobjekten die Referenzen löschen kann.

forumreferenzen.PNG

forumreferenzen2.PNG

Danke schon mal im Voraus :))
 
Poste mal den Stacktrace. Ohne den können wir die Ursache des Crashes nicht wissen.
 
Ich habe die App auf dem Handy, dort steht einfach nur, dass die App angehalten wurde
 
Den Stacktrace findest Du für gewöhnlich im Reiter"Android Monitor" in den Log-Ausgaben, wenn dein Smartphone mit dem Rechner verbunden ist und Du die App via Android Studio startest.

Einfach mal dort reinschauen und den Stacktrace dann posten...
 
FATAL EXCEPTION: main
rocess: com.example.www.test, PID: 8254
java.lang.OutOfMemoryError: Failed to allocate a 2240012 byte allocation with 1979268 free bytes and 1932KB until OOM
at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:837)
at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:656)
at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:1037)
at android.content.res.Resources.loadDrawableForCookie(Resources.java:3980)
at android.content.res.Resources.loadDrawable(Resources.java:3853)
at android.content.res.Resources.getDrawable(Resources.java:1949)
at android.content.Context.getDrawable(Context.java:409)
at android.support.v4.content.ContextCompatApi21.getDrawable(ContextCompatApi21.java:30)
at android.support.v4.content.ContextCompat.getDrawable(ContextCompat.java:372)
at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:202)
at android.support.v7.widget.AppCompatDrawableManager.getDrawable(AppCompatDrawableManager.java:190)
at android.support.v7.content.res.AppCompatResources.getDrawable(AppCompatResources.java:100)
at android.support.v7.widget.AppCompatImageHelper.loadFromAttributes(AppCompatImageHelper.java:54)
at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:66)
at android.support.v7.widget.AppCompatImageView.<init>(AppCompatImageView.java:56)
at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:106)
at android.support.v7.app.AppCompatDelegateImplV9.createView(AppCompatDelegateImplV9.java:1021)
at android.support.v7.app.AppCompatDelegateImplV9.onCreateView(AppCompatDelegateImplV9.java:1080)
at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:47)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:732)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:821)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:821)
at android.view.LayoutInflater.inflate(LayoutInflater.java:511)
at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
at android.view.LayoutInflater.inflate(LayoutInflater.java:366)
at android.support.v7.app.AppCompatDelegateImplV9.setContentView(AppCompatDelegateImplV9.java:288)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:143)
at com.example.www.test.JubelAbschluss2.onCreate(JubelAbschluss2.java:18)
at android.app.Activity.performCreate(Activity.java:6575)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1134)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3137)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3294)
at android.app.ActivityThread.access$1000(ActivityThread.java:210)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1704)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6938)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
Ergänzung ()

habe jetzt mal etwas versucht; allerdings klappt es immer noch nicht. sobald ich das 3. layout geöffnet habe, kommt immer dieselbe fehlermeldung. ich brauche dringend hilfe :(

forumreferenzen3.PNG
 
Warum ist das ein Screenshot und kein Codeblock?
Warum steht da ImageView31? *grusel*
Sollen da etwa 31 Bilder gleichzeitig angezeigt werden!? Lt. Stacktrace wird versucht 2,2MB für ein Bild zu bekommen, bei 31 Bildern also etwa 70MB. Das ist für eine App schon heftig. Damit schließt du eine ganze Reihe an Smartphones als Zielgruppe aus. Auf Tablets könnte das noch hinhauen.

Das Problem ist nicht, dass du die Ressourcen nicht wieder freigibst, du holst dir einfach zu viel auf einmal. Du darfst nur das laden, was auch angezeigt werden soll, dann passts auch mit dem Speicher.
 
Hast du eine Idee, wie ich das lösen kann? Es werden immer nur 19 Bilder pro Seite angezeigt und deswegen wollte ich, dass die Bilder, die nicht auf der aktuellen Seite sind aus dem Arbeitsspeicher geworfen werden. Allerdings weiß ich nicht, wie das geht.
 
Zuletzt bearbeitet:
Aus den Screnshots wird nicht ganz klar, was du eigentlich machen willst. Wenn es nur ein Spinner mit einer Auswahl an Bildern sein soll, ist der erste Google-Treffer der richtige.
 
Ich öffne mit dem Spinner unterschiedliche Layouts, auf denen sich unterschiedliche Bilder (u.a.) befinden. Mein Problem ist nur, dass die App abstürzt, sobald ich das dritte Layout geöffnet habe. Und ich weiß nicht, wie ich das beheben soll.
 
Daraus schließe ich mal, dass die Layouts nicht in einer art Liste angezeigt werden sollen? Sondern?
Und mit "Layouts" meinst du "Aktivitäten"?
Und sollen immer 19 Bilder angezeigt werden? Unabhägig von Auflösung und Orientierung? Bedenke auch, dass Apps deutlich weniger als 64MB zur Verfügung stehen können. Bei Bildern dieser Güte wirst du bei kleineren Geräten auch schnell an das Limit kommen.
 
Ja, 19 Bilder sollen pro Aktivität angezeigt werden und wenn eine Aktivität geschlossen wird, dann sollen die Bilder der geschlossenen Aktivität aus dem Arbeitsspeicher der App gelöscht werden. Und die Bilder der geöffneten Aktivität sollen geladen werden. Dann sollte die App nicht mehr abstürzen.
 
Vllt. hilft das:
http://stackoverflow.com/questions/7075349/android-clear-activity-stack
Eine andere Möglichkeit wäre es die Bilder zu resizen:
http://stackoverflow.com/questions/10413659/how-to-resize-image-in-android
Das spart Speicher.

Du kannst auch überlegen das "Design" zu ändern und nur die Bilder zu ersetzen, anstatt jedesmal eine neue Activity zu öffnen. Wenn die Referenzen auf die neuen Bilder gesetzt werden, dürften die alten Objektreferenzen automatisch gecleart werden.
 
Zuletzt bearbeitet:
Da die Bilder in einem speziellen Layout angezeigt werden sollen, fallen extra für solche Fälle entwickelte Komponenten wie RecyclerView (z.B. http://www.androidauthority.com/how-to-build-an-image-gallery-app-718976/) wohl raus.

D.h. du müsstest die Bilder manuell in onStart() laden und ImageView zuweisen, dann in onStop() wieder entfernen und recyle()n. Falls du die Aktivitäten immer fininsh()st, würde das auch in onCreate() und onDestroy() gehen.
 
Kannst du etwas konkreter werden als "das"? Oder beizehst du dich auf den Post von Serious_Sam?
 
alex_00 schrieb:
Ich habe leider immer noch keine Lösung für mein Problem gefunden. Deswegen habe ich eine Frage an dich, und zwar: Könntest du mir bitte deine letzte Antwort etwas genauer erklären? Ich bin noch ein ziemlicher Anfänger, deswegen verstehe ich nicht genau was ich nun genau machen soll. Ich wäre dir sehr dankbar, wenn du dir die Zeit nehmen würdest und es mir an einem Beispiel erklären könntest, da mein Projekt nun seit fast einem ganzen Monat stillsteht.
Was hast du denn in dem Monat gemacht? Ich gehe mal davon aus, dass du mit den Grundlagen vertraut bist (https://developer.android.com/training/index.html), daher kurz umrissen: Du weist den Imageviews die Bilder direkt im xml-Layout zu, dass muss raus! In der onStart()-Methode lädst du dann die Bilder in die Views und rechnest die vorher ggf. runter (spart Speicher!!!): https://guides.codepath.com/android/Working-with-the-ImageView
In onStop() entfernst und recyclest du die Bilder: http://stackoverflow.com/questions/10200256/out-of-memory-error-imageview-issue

Das wars im Grunde schon.
 
Vielen Dank, es funktioniert (bisher) ganz gut, allerdings gibt es noch einen kleinen Fehler:

Wenn ich mithilfe des Spinner die Activity wechsele, steht dort, die App wäre angehalten. Dann drücke ich auf ok und die App läuft weiter.

Code:
package com.example.www.test;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Spinner;

import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.appindexing.Thing;
import com.google.android.gms.common.api.GoogleApiClient;

public class Jubel extends AppCompatActivity {
    public Spinner spinner1;
    public String[] spinnertext = {"Laufbewegungen", "Abschlussbewegungen (1/2)", "Abschlussbewegungen (2/2)", "EAS FC - Freischaltbare Objekte"};
    public ImageView imageView12;
    public ImageView imageView8;
    public ImageView imageView16;
    public ImageView imageView17;
    public ImageView imageView18;
    public ImageView imageView20;
    public ImageView imageView21;
    public ImageView imageView15;
    public ImageView imageView13;
    public ImageView imageView22;
    public ImageView imageView19;
    public ImageView imageView23;
    public ImageView imageView24;
    public ImageView imageView25;
    public ImageView imageView26;
    public ImageView imageView27;
    public ImageView imageView29;
    public ImageView imageView28;
    public ImageView imageView30;
    public ImageView imageView31;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_jubel);

        imageView12 = (ImageView) findViewById(R.id.imageView12);
        imageView12.setImageResource(R.drawable.thumbsuck2);
        imageView8 = (ImageView) findViewById(R.id.imageView8);
        imageView8.setImageResource(R.drawable.onearmraised1);
        imageView16 = (ImageView) findViewById(R.id.imageView16);
        imageView16.setImageResource(R.drawable.wristflick6);
        imageView17 = (ImageView) findViewById(R.id.imageView17);
        imageView17.setImageResource(R.drawable.aeroplane7);
        imageView18 = (ImageView) findViewById(R.id.imageView18);
        imageView18.setImageResource(R.drawable.pointtosky8);
        imageView20 = (ImageView) findViewById(R.id.imageView20);
        imageView20.setImageResource(R.drawable.canyouhearme11);
        imageView21 = (ImageView) findViewById(R.id.imageView21);
        imageView21.setImageResource(R.drawable.handsout12);
        imageView15 = (ImageView) findViewById(R.id.imageView15);
        imageView15.setImageResource(R.drawable.armsout5);
        imageView13 = (ImageView) findViewById(R.id.imageView13);
        imageView13.setImageResource(R.drawable.eartwist3);
        imageView22 = (ImageView) findViewById(R.id.imageView22);
        imageView22.setImageResource(R.drawable.fingerpoint4);
        imageView19 = (ImageView) findViewById(R.id.imageView19);
        imageView19.setImageResource(R.drawable.telephone10);
        imageView23 = (ImageView) findViewById(R.id.imageView23);
        imageView23.setImageResource(R.drawable.shhhhh9);
        imageView24 = (ImageView) findViewById(R.id.imageView24);
        imageView24.setImageResource(R.drawable.comeon13);
        imageView25 = (ImageView) findViewById(R.id.imageView25);
        imageView25.setImageResource(R.drawable.doublearmswing15);
        imageView26 = (ImageView) findViewById(R.id.imageView26);
        imageView26.setImageResource(R.drawable.flyingbird16);
        imageView27 = (ImageView) findViewById(R.id.imageView27);
        imageView27.setImageResource(R.drawable.handonhead17);
        imageView29 = (ImageView) findViewById(R.id.imageView29);
        imageView29.setImageResource(R.drawable.armspointingup19);
        imageView28 = (ImageView) findViewById(R.id.imageView28);
        imageView28.setImageResource(R.drawable.heartsymbol18);
        imageView30 = (ImageView) findViewById(R.id.imageView30);
        imageView30.setImageResource(R.drawable.windmill20);
        imageView31 = (ImageView) findViewById(R.id.imageView31);
        imageView31.setImageResource(R.drawable.blowkisses14);


        spinner1 = (Spinner) findViewById(R.id.spinner1);


        ArrayAdapter<String> spinneradapter = new ArrayAdapter<String>(Jubel.this, android.R.layout.simple_spinner_dropdown_item, spinnertext);
       spinner1.setAdapter(spinneradapter);
        spinner1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {


            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                int spinnerposition = spinner1.getSelectedItemPosition();

                switch (spinnerposition) {

                    case 0: {
                        break;
                    }

                    case 1: {
                        onDestroy();
                        Intent intent = new Intent(Jubel.this,JubelAbschluss.class);
                        startActivity(intent);
                        break;
                    }

                    case 2: {
                        onDestroy();
                        Intent intent = new Intent(Jubel.this,JubelAbschluss2.class);
                        startActivity(intent);
                        break;
                    }

                    case 3: {
                        onDestroy();
                        Intent intent = new Intent(Jubel.this,JubelEAS.class);
                        startActivity(intent);
                        break;

                    }
                }
            }
                    @Override
                    public void onNothingSelected (AdapterView < ? > parent){

                    }
                } );}

    public void ToHome(View view) {

        onDestroy();
        Intent intent = new Intent(this,MainActivity.class);
        startActivity(intent);
    }

    @Override
    public void onDestroy() {
      super.onDestroy();

        imageView12.setImageDrawable(null);
        imageView8.setImageDrawable(null);
        imageView16.setImageDrawable(null);
        imageView17.setImageDrawable(null);
        imageView18.setImageDrawable(null);
        imageView20.setImageDrawable(null);
        imageView21.setImageDrawable(null);
        imageView15.setImageDrawable(null);
        imageView13.setImageDrawable(null);
        imageView22.setImageDrawable(null);
        imageView19.setImageDrawable(null);
        imageView23.setImageDrawable(null);
        imageView24.setImageDrawable(null);
        imageView25.setImageDrawable(null);
        imageView26.setImageDrawable(null);
        imageView27.setImageDrawable(null);
        imageView29.setImageDrawable(null);
        imageView28.setImageDrawable(null);
        imageView30.setImageDrawable(null);
        imageView31.setImageDrawable(null);
    }
}


Das ist der Stracktrace:

Code:
02-23 23:12:35.174 22064-22064/com.example.www.test E/AndroidRuntime: FATAL EXCEPTION: main
                                                                      Process: com.example.[url]www.test[/url], PID: 22064
                                                                      java.lang.RuntimeException: Unable to pause activity {com.example.www.test/com.example.www.test.Jubel}: java.lang.IllegalStateException: No activity
                                                                          at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4429)
                                                                          at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4388)
                                                                          at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:4363)
                                                                          at android.app.ActivityThread.access$1200(ActivityThread.java:210)
                                                                          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1715)
                                                                          at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                          at android.os.Looper.loop(Looper.java:145)
                                                                          at android.app.ActivityThread.main(ActivityThread.java:6938)
                                                                          at java.lang.reflect.Method.invoke(Native Method)
                                                                          at java.lang.reflect.Method.invoke(Method.java:372)
                                                                          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
                                                                          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
                                                                       Caused by: java.lang.IllegalStateException: No activity
                                                                          at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1568)
                                                                          at android.support.v4.app.FragmentManagerImpl.dispatchPause(FragmentManager.java:2846)
                                                                          at android.support.v4.app.FragmentController.dispatchPause(FragmentController.java:234)
                                                                          at android.support.v4.app.FragmentActivity.onPause(FragmentActivity.java:448)
                                                                          at android.app.Activity.performPause(Activity.java:6731)
                                                                          at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1338)
                                                                          at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4415)
                                                                          at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4388) 
                                                                          at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:4363) 
                                                                          at android.app.ActivityThread.access$1200(ActivityThread.java:210) 
                                                                          at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1715) 
                                                                          at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                          at android.os.Looper.loop(Looper.java:145) 
                                                                          at android.app.ActivityThread.main(ActivityThread.java:6938) 
                                                                          at java.lang.reflect.Method.invoke(Native Method) 
                                                                          at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                          at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404) 
                                                                          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
 
Schön, dass du zumindest einen Bruchteil von meinem Post umgesetzt hast.
Du musst dir aber unbedingt (nochmal?) die Grundlagen der App-Programmierung durchlesen. Z.B. NIEMALS die onDestroy()-Methode manuell aufrufen!!! Daher kommt höchstwahrscheinlich die Fehlermeldung. Schau dir nochmal an, wie man eine Aktivität richtig beendet.
 
Welchen Befehl soll ich statt onDestroy() benutzen? Ich habe finish() versucht, aber das ging auch nicht.
 
onDestroy ist eine Methode aus dem Activity Lifecycle und wird vom System aufgerufen. Allgemein macht es keinen Sinn eine Activity in der onDestroy aufzurufen Siehe hier.

Versuche doch mal in der onStop Methode folgenden Aufruf:
Code:
((BitmapDrawable)imageView.getDrawable()).getBitmap().recycle();
wie es Darlis geschrieben hat.
 
Zurück
Oben