Aus Fragment Klasse scheitert der zweite Aufruf eines Dialogs mit Null Pointer

  • 6 Antworten
  • Letztes Antwortdatum
Punisher

Punisher

Stamm-User
279
Hey Leute, ich bin jetzt lange ohne eure Hilfe klar gekommen aber jetzt finde ich einfach keine Lösung meines Problems. Ich sag mal dazu das ich erst relativ kurz dabei bin und die Java Grundlagen leider immer noch nicht ganz gefestet sind. Ich hoff ihr helft mir trotzdem :razz:

Ich fang mal an wie meine App aufgebaut ist.

Beim starten der MainActivity wird eine Horizontal Swipe View mit 12 Fragmenten erzeugt. Das klappt.

Das erste Fragment heißt Fragment0 und erbt Fragment mit extends. Im Fragment0 Layout sind mehrere Buttons (Monat Januar, Jeder Tag ein Button) und TextViews. Diese habe ich in OnCreate alle so initialisiert mit
view v = inflater.inflate(R.layout.fragment0_layout, null);
buttonJan1 = (Button) v.findViewById(R.id.btnJan1);

Die Buttons werden alle mit OnClick überwacht und funktionieren weil sie in der DatumTextView ihr Datum setzen und ein extra Button janAdd sichtbar wird wenn einer der 31 Buttons für die Tage im Januar gedrückt wird.

Beim Drücken des Buttons janAdd sollen mehrere Dialoge starten und die Auswahl an das Fragment 0 wieder zurück geben.


Der Button janAdd startet den ersten Dialog so.
DialogFragment newFragment = new schichtListPicker();
newFragment.show(getFragmentManager(), "schichtListPicker");

Die klasse schichtListPicker sieht so aus.
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;

public class schichtListPicker extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.waehleSchicht);
builder.setItems(R.array.fruehSpaetNachtschicht, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
Fragment0 Fragment = new Fragment0();
Fragment.setSchicht(id);

}
});
return builder.create();
}

}

Die Methode wo die Auswahl aus dem Dialog übergeben wird sieht so aus wo der Null Pointer dann auch entsteht. (Die Übergabe ist oben Rot markiert)

public void setSchicht(int id){
if (id == 0){
textViewJanSchicht.setText("Frühschicht");
DialogFragment newFragment = new welcheSchichtPicker();
newFragment.show(getFragmentManager(), "welcheSchichtPicker");

Bis zum textViewJanSchicht.setText("Frühschicht"); funktioniert alles wie gewünscht. Hatte vorher das Problem, dass die textViewJanSchicht auch eine NullPointer geworfen hat. Sie konnte nicht mehr gefunden werden. Nachdem ich aus "TextView = textViewJanSchicht" dies "public static TextView = textViewJanSchicht" gemacht hab funktioniert es.

Ich denke das gleiche Problem hab ich auch beim aufrufen des zweiten Dialogs wo ich kein Plan hab wie ich das lösen soll :/
newFragment.show(getFragmentManager(), "welcheSchichtPicker");
Hier wird der NullPointer geworfen. Komischweise kann ich alle dialoge einzeln aufrufen aber wenn ein zweiter aufgerufen wird scheint nichts mehr initialisiert zu sein.

Hat einer ne Idee?
 
02-23 12:55:56.528: E/AndroidRuntime(16066): FATAL EXCEPTION: main
02-23 12:55:56.528: E/AndroidRuntime(16066): java.lang.NullPointerException
02-23 12:55:56.528: E/AndroidRuntime(16066): at android.support.v4.app.DialogFragment.show(DialogFragment.java:125)
02-23 12:55:56.528: E/AndroidRuntime(16066): at de.chr.baum.kmwschicht6.Fragment0.setSchicht(Fragment0.java:138)
02-23 12:55:56.528: E/AndroidRuntime(16066): at de.chr.baum.kmwschicht6.schichtListPicker$1.onClick(schichtListPicker.java:17)
02-23 12:55:56.528: E/AndroidRuntime(16066): at com.android.internal.app.AlertController$AlertParams$3.onItemClick(AlertController.java:941)
02-23 12:55:56.528: E/AndroidRuntime(16066): at android.widget.AdapterView.performItemClick(AdapterView.java:298)
02-23 12:55:56.528: E/AndroidRuntime(16066): at android.widget.AbsListView.performItemClick(AbsListView.java:1102)
02-23 12:55:56.528: E/AndroidRuntime(16066): at android.widget.AbsListView$PerformClick.run(AbsListView.java:2751)
02-23 12:55:56.528: E/AndroidRuntime(16066): at android.widget.AbsListView$1.run(AbsListView.java:3425)
02-23 12:55:56.528: E/AndroidRuntime(16066): at android.os.Handler.handleCallback(Handler.java:725)
02-23 12:55:56.528: E/AndroidRuntime(16066): at android.os.Handler.dispatchMessage(Handler.java:92)
02-23 12:55:56.528: E/AndroidRuntime(16066): at android.os.Looper.loop(Looper.java:137)
02-23 12:55:56.528: E/AndroidRuntime(16066): at android.app.ActivityThread.main(ActivityThread.java:5195)
02-23 12:55:56.528: E/AndroidRuntime(16066): at java.lang.reflect.Method.invokeNative(Native Method)
02-23 12:55:56.528: E/AndroidRuntime(16066): at java.lang.reflect.Method.invoke(Method.java:511)
02-23 12:55:56.528: E/AndroidRuntime(16066): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
02-23 12:55:56.528: E/AndroidRuntime(16066): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
02-23 12:55:56.528: E/AndroidRuntime(16066): at dalvik.system.NativeStart.main(Native Method)

Hier noch der Logcat
 
Hi Punisher,

willkommen in der Java-Welt und vorallem bei Android.
Könntest Du mal deinen ganzen Code posten? Schön wären gleich noch die Zeilennummern, weil der Stacktrace (deine Fehlermeldung) mit Zeilennummern versehen ist und daraus ziemlich deutlich wird was passiert, wenn man denn die Zeilen zuordnen kann.

Fragment0 Fragment = new Fragment0();
Fragment.setSchicht(id);


Diese Zeilen werden keine NullPointerException (NPE) auslösen, weil das Objekt direkt eine Zeile vor seiner Nutzung instanziert wird. Allerdings kann natürlich eine NPE innerhalb der Methode setSchicht auftreten, wenn dort etwas nicht initialisiert wurde. Man würde übrigens den Objektnamen klein Schreiben (Fragment0 fragment = new Fragment0()) - ist eine Konvention zur besseren Lesbarkeit.

"public static TextView textViewJanSchicht = new TextView();" ist eine statische Klassenvariable/Klassenfeld. Du möchtest eigentlich auf Objektebene arbeiten.
"private TextView textViewJanSchicht = new TextView();". Wobei die Initialisierung (Erzeugung des Objects mit new) in die onCreate Methode gehört.

Um mal konkret zu fragen:
Was steht bei DialogF ragment.java in Zeile 125?
Ich vermute dein textViewJanSchicht ist Null weil nur lokal initialisiert.
 
  • Danke
Reaktionen: Punisher
Habs mir nochmal angesehen, auch ohne Zeilennummern kann ich sagen, dass dein Problem hier liegt:

DialogFragment newFragment = new welcheSchichtPicker();
newFragment.show(getFragmentManager(), "welcheSchichtPicker");

Genauer gesagt sehe ich die Ursache darin, dass getFragmentManager() null zurückliefert und dann in der show Methode vom DialogFragment eine NPE auslöst. Wie initalisierst Du den FragmentManager? Gibt getFragmentManager() den initialisierten Manager zurück, oder eben null?

Hab selbst noch nicht mit DialogFragment gearbeitet, aber rein aus Java-Sicht wird hier null geliefert werden.

Zumindest wenn ich nach dem Code der DialogFragment Klasse gehe:
public void [More ...] show(FragmentManager manager, String tag) {
mDismissed = false;
mShownByMe = true;
FragmentTransaction ft = manager.beginTransaction(); //Zeile 125
ft.add(this, tag);
ft.commit();
}

Interessant wäre auch deine Klasse:
welcheSchichtPicker (sollte man übrigens groß schreiben).
Du erbst nämlich offensichtlich von DialogFragment und evtl. hast Du dabei schon einen Fehler gemacht.
 
  • Danke
Reaktionen: Punisher
Erstmal vielen Dank!!! :D

Hab die ganze Zeit gedacht die NPE kommt vom "new welcheSchichtPicker()". Das er die Klasse einfach nicht findet. Dein Tipp das getFragmentManager() die null zurück gibt war richtig und ich konnte dann mit Hilfe von Google das Problem lösen auch wenn ich es noch nicht ganz verstehe.

Hab jetzt ne Variable erstellt.
public static FragmentManager startDialog;

Dann in OnCreate getFragmentManager initialisiert.
startDialog = getFragmentManager();

Den Dialog erzeuge ich nun so.
DialogFragment newFragment = new WelcheSchichtPicker();
newFragment.show(startDialog , "welcheSchichtPicker");

Ich hab bisher den Fragment Manager nie initialisiert. Hab das ganze vorher erstmal in der MainActivity (mit Extends FragmentActivity) getestet und konnte die Dialoge immer problemlos auf die gleiche Weise starten. Nachdem ich nun den gleichen Code aus Fragment0 (mit Extends Fragment) starte muss ich den FragmentManager initialisieren. :huh:
Es finds auch komisch das es erst initialisiert ist und nachdem der erste Dialog aufgerufen wurde nicht mehr...

Kannst du mir das erklären?
 
Du mußt immer ein Objekt initialisieren, bevor Du es benutzen kannst.
Wenn Du natürlich erbst kann es sein, dass die verwendeten Objekte von der beerbten Klasse initalisiert wurden (zum Beispiel im Super-Konstruktor).

Dein "public static FragmentManager startDialog;" gefällt mir nicht so recht.
Das "static" bedeutet, dass es sich um eine Klassenvariable / Klassenfeld handelt. Also egal wieviele Objekte deiner Klasse du mit "new" instanzierst, alle greifen auf dieses Feld zu. Da Du in onCreate() die initialisierung durchführst, würde der FragmentManager immer wieder neu initialisiert, für ALLE instanzierten Objekte.
Typischerweise schreibst Du "private FragmentManager startDialog;".
"public" würde man bei objekt orientierter Programmierung auch nicht verwenden, denn dann könnte man von "außen" auf die Felder zugreifen und diese verändern, ohne dass das Objekt darauf Einfluß nehmen könnte.

Als Anfänger sind diese Konzepte natürlich nicht einfach zu verstehen und es ist viel auf einen Schlag. Sieh ein Objekt einfach als eine abgeschlossene Kiste die sich und seine Attribute (Felder/Variablen) selbst verwaltet.
Klassenvariablen sind dann Variablen die auf der Blaupause stehen, die benutzt wird um weitere Objekte zu erzeugen. Die Blaupause (Klasse) ist einzigartig und alle auf ihr stehenden Klassenvariablen sind für alle Objekte, die aus ihr instanziert wurden, verfügbar.

Mit "static" solltest Du dich erst später beschäftigen und auch erst dann wenn Du es wirklich brauchst.
So kann man zum Beispiel alle Instanzierungen in so einer Klassenvariable zählen.
 
Ok, ich werde mir das wohl nochmal genauer anschauen müssen aber danke das du mir so ausführlich Antwortest. Hat mir sehr geholfen und ich denke dieses Problem wird mich ne Stufe höher bringen.

Bist ja erst kurz hier dabei. Ich hoffe du bleibst weiterhin so hilfsbereit und nochmal vielen Dank :)
 
Zurück
Oben Unten