NullPointerException.... aber warum?

D

DrLiightninG

Neues Mitglied
1
Hallo zusammen,
ich erhalte in einer meiner Methoden ständig eine NullPointerException, die ich mir einfach nicht erklären kann...
Es handelt sich um einen CustomAdapter, welcher in einer tabbed Activity im ersten Tab initialisiert wird. Anschließend wird mit dessen Hilfe eine ListView mit Einträgen gefüllt. Soweit funktioniert alles.
Das Problem tritt nun auf, wenn ich versuche nachträglich Items zu der ListView und dem CustomAdapter hinzuzufügen. Mein Adapter schein nämlich nun "null" zu sein. Dabei wurde er doch vorher schon längst initialisiert und auch schon verwendet?!

Hier der Fehlercode:
Code:
FATAL EXCEPTION: main
                                                                            Process: com.kronenberg.jan.goparty, PID: 16069
                                                                            java.lang.NullPointerException: Attempt to invoke virtual method 'void com.kronenberg.jan.goparty.PartyAdapter.add(com.kronenberg.jan.goparty.PartyItem)' on a null object reference
                                                                                at com.kronenberg.jan.goparty.MainActivity$PlaceholderFragment.addPartyFav(MainActivity.java:646)

In dieser Methode tritt der Fehler auf:
Code:
public void addPartyFav(PartyItem pItem) {
            Toast.makeText(getActivity().getApplicationContext(), "addPartyFav (ID: " + pItem.getPartyID() + ")",Toast.LENGTH_LONG).show();
            favList.add(pItem.getPartyID());
            favString = "";
            for(int i = 0; i < favList.size(); i++) {
                favString = favString + favList.get(i) + ",";
            }

            pItem.setPartyFav(true);
            gpartyAdapter.add(pItem); //Hier ist der Fehler

            SharedPreferences sharedPrefs = getActivity().getSharedPreferences("GoPartyDaten", 0);
            SharedPreferences.Editor editor = sharedPrefs.edit();
            editor.putString("FavString", favString);
            editor.commit();
        }

Hier wird der Adapter initialisiert:
Code:
if(firstLoad) {

                        gpartyAdapter = new PartyAdapter(getActivity(), R.layout.list_item_new);
                        gpartyAdapter.setAct(this);
                        gpartyList.setAdapter(gpartyAdapter);
//....
}
//...
partyItem = new PartyItem(id, partyName, clubName, zeit, adresse,true);
gpartyAdapter.add(partyItem); //Hier wird die ListView zum ersten Mal erstellt. Dies klappt einwandfrei.
//...

Ich hoffe jemand findet meinen Fehler.

Gruß
Jan
 
Ich vermute, es die Reihenfolge nicht. D.h. du rufst den Adapter auf, bevor du eine Instanz des Adapter erzeugt.

Er setzte doch einfach mal die Abfrage if(firstLoad) durch if (gpartyAdapter==null).

Und schau mal nach, ob überhaupt eine Instanz des Adapter erzeugt wird.
 
Hallo jan,

1) eigentlich gibt es im Androidstudio die Ausgabe der Errors und da steht auch schön an welcher Zeile es abstürzt (sogar mit link und click) und welches Objekt in dem Moment NULL ist .
2) implementier doch mal bitte ein try / catch, und lass dir E als String ausgeben , dann erfährst du noch mehr

lg stefan
 
markus.tullius schrieb:
Ich vermute, es die Reihenfolge nicht. D.h. du rufst den Adapter auf, bevor du eine Instanz des Adapter erzeugt.

Er setzte doch einfach mal die Abfrage if(firstLoad) durch if (gpartyAdapter==null).

Und schau mal nach, ob überhaupt eine Instanz des Adapter erzeugt wird.

gpartyAdapter wird initialisiert. Das habe ich mir ausgeben lassen. Ansonsten wäre ja auch die Erstellung der ListView mit diesem Adapter nicht möglich. Diese wird jedoch am Anfang erfolgreich erstellt.
In der Methode "addPartyFav" ist der Adapter jedoch plötzlich wieder null. Habe ich mir ebenfalls ausgeben lassen mit deiner vorgeschlagenen if-Abfrage. Nur warum der Adapter wieder null wird, weiß ich nicht.

swa00 schrieb:
Hallo jan,

1) eigentlich gibt es im Androidstudio die Ausgabe der Errors und da steht auch schön an welcher Zeile es abstürzt (sogar mit link und click) und welches Objekt in dem Moment NULL ist .
2) implementier doch mal bitte ein try / catch, und lass dir E als String ausgeben , dann erfährst du noch mehr

lg stefan

Ich habe den Fehlerbereich ja gepostet. Die Zeile ist oben in meinem ersten Beitrag kommentiert. Der gpartyAdapter ist null, obwohl er vorher nicht null war und eine funktionierende ListView erzeugt hat.
Wie genau meinst du das mit dem "lass dir E als String ausgeben"?
 
DrLiightninG schrieb:
Wie genau meinst du das mit dem "lass dir E als String ausgeben"?

Im catch rufst du die Methode getMessage() des Objektes im Parameter auf

Code:
...
catch(Throwable t)
{
    Log.e(t.getMessage());
}
 
@DrLiightninG,

mit dem Fehlerbericht ist alles okay. Du hast schon die richtige Fehlermeldung gepostet.

Ich habe eine Verständnisfrage:

Soweit ich sehe, tritt der Fehler im der inneren Klasse PlaceholderFragment auf. Erzeugt du die Instanz des Adapters auch im PlaceholderFragment, oder in der MainActivity?
 
Jaiel schrieb:
Im catch rufst du die Methode getMessage() des Objektes im Parameter auf

Code:
...
catch(Throwable t)
{
    Log.e(t.getMessage());
}

Werde ich nachher mal machen.

markus.tullius schrieb:
@DrLiightninG,

mit dem Fehlerbericht ist alles okay. Du hast schon die richtige Fehlermeldung gepostet.

Ich habe eine Verständnisfrage:

Soweit ich sehe, tritt der Fehler im der inneren Klasse PlaceholderFragment auf. Erzeugt du die Instanz des Adapters auch im PlaceholderFragment, oder in der MainActivity?
Ja das läuft alles in der inneren Klasse PlaceholderFragment ab. Dort sind ja per if-Abfrage drei Bereiche, für die drei Tabs der TabbedActivity vorgesehen.
An dieser Stelle startet das Ganze dann:
Code:
if(getArguments().getInt(ARG_SECTION_NUMBER) == 1) { //Bereich für den ersten Tab
//...
}
Dort wird ein BackgroundTask erstellt, der MySQL Daten per PSON ausliest und später an eine Methode der PlaceholderFragment Klasse übergibt.
In dieser Methode wird (wie in meinem ersten Post gezeigt) der gpartyAdapter initialisiert und die ListView erstellt. Dies klappt auch alles.
Wenn ich dann aber auf den zweiten Tab wechsel und dort ein Event auslöse, wodurch der ListView aus dem ersten Tab ein neues Item hinzugefügt werden soll, bekomme ich diese NullPointerException.
 
Wenn ich deine Erklärung richtig verstehe, wechselst du beim Drücken des Tabs den Views deines PlaceholderFragments. Ich würde sogar vermuten, dass du ein komplett neues Fragment erzeugst.
Wenn die zutreffen sollt, löschst Du dabei auch den Adapter. Wenn du dann den Adapter dann aufrufst, gibt es dort keine Referenz mehr auf einem Objekt.
 
markus.tullius schrieb:
Wenn ich deine Erklärung richtig verstehe, wechselst du beim Drücken des Tabs den Views deines PlaceholderFragments. Ich würde sogar vermuten, dass du ein komplett neues Fragment erzeugst.
Wenn die zutreffen sollt, löschst Du dabei auch den Adapter. Wenn du dann den Adapter dann aufrufst, gibt es dort keine Referenz mehr auf einem Objekt.

Das wird es vermutlich sein. Nur wie kann ich das beheben? Den Adapter immer wieder neu zu erstellen bringt mir nichts, da dann die bereits eingefügten Items verloren gehen.
 
Es gibt zwei gängige Weg:

a) Du speicherst die Werte (z.B. in einer sqlite Datenbank o. in den SharedPreferences) bevor du das Fragment schließt.

b) Du speicherst die Werte in der Activity, welche die Fragmente hält.

Mit den Werten füllst du dann das neue Fragment.
(Wenn Du nicht gerade tausende von rows hast, klappt das ganz gut.)
 
b) würde schon ausreichen mMn -> KISS
 
markus.tullius schrieb:
a) Du speicherst die Werte (z.B. in einer sqlite Datenbank o. in den SharedPreferences) bevor du das Fragment schließt.
Danke, funktioniert :)
 
KISS
:huh:
 
"b) würde schon ausreichen mMn -> KISS"
=
"Meiner Meinung nach würde die Option b) die vorgeschlagen wurde ausreichen. Ganz nach dem Prinzip von 'Keep it simple stupid!' sollte man es nie komplizierter umsetzen als es notwendig ist"

mMn - meiner Meinung nach
KISS - Keep it simple stupid
 
markus.tullius schrieb:
KISS: KISS-Prinzip – Wikipedia

Macht nichts. a) ist die sichere Lösung, weil die Daten permanent gespeichert sind.

Jetzt nur mal theoretisch... Wenn du das zu oft machst und die app andauernd verwendet wird könnte man durchaus möglicherweise in die Gefahr laufen, den speicher zu oft zu überschreiben.

An deiner Stelle hätte ich einfach den adapter statisch gemacht.

Also
Code:
public static PartyAdapter gpartyAdapter;
Dann initialisieren und er bleibt auch initialisiert.
Falls du aber mehrere Adapter brauchst, kannst du ja einfach mehrere statisch machen. Somit wäre das Problem behoben.
 
Der Adapter hält das Context-Objekt der Activity. Da stellen sich bei mir grad die Alarmglocken an, wenn das static werden soll :O
 
Zu recht. Eine gute Möglichkeit ein Speicherleck zu erzeugen. Ich glaube, damit fangen die Probleme eher erst an. Statische Variablen führen dazu, das Activities oder Fragmente nicht aus dem Speicher erlöschst werden, wenn sie beendet werden. Der GC(Garbage Collection) lässt sie stehen, weil noch eine Referenz auf die Statische Variable besteht. Und wenn in der entstandenen Speicherinsel noch ein Thread läuft, dann "Gute Nacht". Denn Fehler zu finden kostet extrem viel Nerven und Zeit.

Und normalerweise spielen die Schreibzyklen bei Smartphones keine so große Rolle. Die wenigsten Smartphones sind solange in Betrieb.
(Wenn ich das noch recht im Kopf habe, müsste ich auf ein 32GB Flash Speicher pro Tag 5 GB Daten in 3 Jahre schreiben, bevor wirklich Probleme auftreten.)
 
@markus.tullius also wenn das so ist... Da hast du Recht. Was aber dann eigentlich mit meinem alten S3 mini passiert ist, sodass der eMMC hinterher dann schreibgeschützt war, ist dann wohl unklar. Oder es war einfach ein fehlerhafter chip.
 

Ähnliche Themen

A
Antworten
10
Aufrufe
1.021
swa00
swa00
S
Antworten
3
Aufrufe
636
swa00
swa00
Zurück
Oben Unten