FragmentPagerAdapter - ForceClose wenn Tab Inhalt enthält

  • 5 Antworten
  • Letztes Antwortdatum
MDXDave

MDXDave

Ehrenmitglied
1.626
Hallo,
ich hab da ein kleines Problem.

Ich habe eine kleine App geschrieben die einen Stundenplan meiner FH anzeigt.
Das ganze wird in SlidingTabs (mit Swipe) realisiert.

Der Stundenplan wird via JSON von einem Server geladen und dann in einer ListView ausgegeben.

Das Problem ist nun folgendes, wenn ich 5 "Tabs" (also Sliding-Fragmente) erstellen lasse und beim Starten der App eines der 5 automatisch anzeigen möchte, erhalte ich eine NullPointer-Exception und die App wird beendet, sobald ich allerdings 7 Tabs erstellen lasse (mit 6 funktioniert es ebenfalls nicht) und den letzten aufrufe, funktioniert alles, kann also dann auch zu Tab 5-1 "swipen".

Erstellen lasse ich die Fragmente in einem AsyncTask in der PostExecute-Funktion:
Code:
[...]
StdMontag = new StundenPlanFragment0(json,"1");
StdDienstag = new StundenPlanFragment0(json,"2");
StdMittwoch = new StundenPlanFragment0(json,"3");
StdDonnerstag = new StundenPlanFragment0(json,"4");
StdFreitag = new StundenPlanFragment0(json,"5");
[...]

(json ist ein JSONObjekt in der der JSON-Quellcode enthalten ist)
GetItem sieht so aus:

Code:
 public class SectionsPagerAdapter extends FragmentPagerAdapter {  
		  
	        public SectionsPagerAdapter(FragmentManager fm) {  
	            super(fm);  
	        }  
	  
	        @Override  
	        public Fragment getItem(int position) {  
	            Fragment fragment = new Fragment();  
	            switch (position) {  
	            case 0:  
	                return fragment = StdMontag;  
	            case 1:
	            	return fragment = StdDienstag;
	            case 2:
	            	return fragment = StdMittwoch;
	            case 3:
	            	return fragment = StdDonnerstag;
	            case 4:
	            	return fragment = StdFreitag;
	            

	            default:  
	                break;  
	            }  
	            return fragment;  
	        }
	  
	        @Override  
	        public int getCount() {  
 
	            return 7;  
	        }  
	  
	        @Override  
	        public CharSequence getPageTitle(int position) {  
	            Locale l = Locale.getDefault();  
	            switch (position) {  
	            case 0:  
	                return getString(R.string.montag);  
	            case 1:  
	                return getString(R.string.dienstag);  
	            case 2:  
	                return getString(R.string.mittwoch);
	            case 3:  
	                return getString(R.string.donnerstag);
	            case 4:  
	                return getString(R.string.freitag);
	            }  
	            return null;  
	        }  
	    }


Die genaue Fehlermeldung:
10-14 02:52:48.167: E/AndroidRuntime(21649): FATAL EXCEPTION: main
10-14 02:52:48.167: E/AndroidRuntime(21649): java.lang.NullPointerException
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.support.v4.app.BackStackRecord.doAddOp(BackStackRecord.java:394)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.support.v4.app.BackStackRecord.add(BackStackRecord.java:389)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.support.v4.app.FragmentPagerAdapter.instantiateItem(FragmentPagerAdapter.java:99)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.support.v4.view.ViewPager.addNewItem(ViewPager.java:832)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.support.v4.view.ViewPager.populate(ViewPager.java:982)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.support.v4.view.ViewPager.populate(ViewPager.java:914)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1436)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.View.measure(View.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.widget.FrameLayout.onMeasure(FrameLayout.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.View.measure(View.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at com.android.internal.widget.ActionBarOverlayLayout.onMeasure(ActionBarOverlayLayout.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.View.measure(View.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.widget.FrameLayout.onMeasure(FrameLayout.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.View.measure(View.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.Choreographer$CallbackRecord.run(Choreographer.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.Choreographer.doCallbacks(Choreographer.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.Choreographer.doFrame(Choreographer.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.os.Handler.handleCallback(Handler.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.os.Handler.dispatchMessage(Handler.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.os.Looper.loop(Looper.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at android.app.ActivityThread.main(ActivityThread.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at java.lang.reflect.Method.invokeNative(Native Method)
10-14 02:52:48.167: E/AndroidRuntime(21649): at java.lang.reflect.Method.invoke(Method.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
10-14 02:52:48.167: E/AndroidRuntime(21649): at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:112)
10-14 02:52:48.167: E/AndroidRuntime(21649): at dalvik.system.NativeStart.main(Native Method)

Ich hoffe mal mir kann jemand helfen :/
 
Du hast die Antwort schon gegeben. Du erstellst deine Fragments in einem AsyncTask. Das ist schlichtweg zu spät, weil die Fragments schon angezeigt werden müssen.

Es ist auch logisch, dass es mit 7 Fragments klappt. Deine getItem() Methode liefert nur bei 0-4 die null Fragmente zurück. Wenn du aber Fragment 7 zuerst anzeigst, braucht der PagerAdapter nur Fragment 5 und 6. (Übrigens, deine getItem() Methode ist sehr umständlich, weil du bei Item 0-4 ein unnützes Fragment im Speicher erstellst)

Solange die Inhalte noch geladen werden, solltest du eine Ladeanimation anzeigen.
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: MDXDave und kleinerkathe
Wie soll ich das ganze denn sonst realisieren? Mit würde einfallen die Daten und die Fragmente bereits in meiner StartActivity beim Klick auf Stundenplan zu erstellen und diese dann an die StundenplanActivity zu übergeben, oder gibt es eine bessere Möglichkeit?
 
Die Daten am Anfang holen und dann zu übergeben kann man machen.
Die Fragmetne würde ich erst erstellen wenn du sie wirklich brauchst. Also diese im Adapter erstellen lassen.

Du könntest die Daten auch auf dem Handy zwischenspeichern, oder die Daten vom Fragment aus dem Internet saugen lassen.

lg. Dagobert
 
Wie du es sonst realisieren sollst? Du hast so viel Möglichkeiten. Zu denen von DagobertDokate fallen mir noch ein paar ein:

Alle 7 Fragmente anzeigen und solange noch keine Daten sind eine Ladeanimation in den einzelnen Fragments anzeigen (die Fragments laden dann die Daten für sich).

Im Adapter die Anzahl dynamisch festlegen. Solange keine Daten da sind, werden nur 2 Fragments für das Wochenende angezeigt. Wenn die Daten da sind, die Anzahl wieder auf 7 Fragments setzen.

Solange die Daten nicht da sind, ein einziges Fragment anzeigen mit der Info, dass die Daten noch geladen werden. Sind sie da, zeigst du die Fragments an.
 
  • Danke
Reaktionen: MDXDave
Danke euch!

Ihr habt mir mein Denkfehler aufgezeigt, ist ja eigentlich logisch dass meine App kein Fragment anzeigen kann was null ist, was es aber ja automatisch macht wenn ich die Activity starte (zumindest wie der Code bisher war). Der Progressdialog wurde ja nur darüber gelegt, der ViewPager wird jetzt erst in OnPostExecute mit Inhalt gefüllt und es funktioniert nun, eigentlich ja ziemlich simpel ^^

Danke jedenfalls :)
 
Zurück
Oben Unten