2015-05-18 11 views
9

Kürzlich stieß ich auf ein schwer reproduzierbares Problem. Der NPE tritt auf, wenn ein Fragment versucht, ArrayAdapter mit den Daten von Activity zu initialisieren. Die Standardliste in Aktivität des onCreate Methode initialisiert:Warum Fragment onCreate() wird manchmal vor Activity onCreate() aufgerufen?

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    // ... 
    mAccounts = new ArrayList<>(); 
    // ... 
} 

@Override 
public List<Account> getAccounts(){ 
    return mAccounts; 
} 

Das Fragment erstellt eine Liste Adapter auch in seiner onCreate():

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setRetainInstance(true); 
    setHasOptionsMenu(true); 

    //mAccountProvider is an interface implemented by the activity 
    mAccounts = mAccountProvider.getAccounts(); 

    mAccountAdapter = new AccountAdapter(getActivity(), R.layout.account_list_item, mAccounts); 
} 

Die NPE tritt innerhalb des AccountAdapter wenn Standard getCount() Methode wird aufgerufen. Der Grund ist, dass mAcocounts null ist. Das Problem tritt selten auf und ich konnte es nicht reproduzieren.

Wann ist es möglich, dass das Fragment onCreate() vor onCreate Aktivität() genannt wird? Nach dem Quellcode wird Fragments onCreate() in der Aktivität onCreate() gesendet. Warum wird es aufgerufen, nachdem Activity onCreate() seine Ausführung beendet hat?

+0

nein es ist nicht möglich. – Blackbelt

+0

Sie sollten mehr Code darüber veröffentlichen, wie Ihr Fragment in Ihrer Aktivität angezeigt wird. – jobcrazy

+0

Ich stimme @Ilya Vorobiev zu. Das onCreate() des Fragments wird ausgelöst, wenn super.onCreate() der Aktivität aufgerufen wird. Die Frage ist, warum es in den meisten Fällen nach dem onCreate der Aktivität ausgeführt wird. – Zzokk

Antwort

5

onCreate() Ihres Fragments kann aufgerufen werden, bevor onCreate() Methode Ihrer Aktivität abgeschlossen wurde. Sie haben onActivityCreated() Rückruf in Ihrem Fragment und onCreateView(). Sie können jedes davon verwenden - es führt nach onCreate Methode der Aktivität.

+0

Kennen Sie die genauen Umstände? Wie ich schon erwähnt habe, ist das Thema selten wiedergegeben. – Zzokk

+0

Es gibt viele Situationen, in denen dieses Problem auftritt. Wenn Sie sich die onCreate() - Methode von FragmentActivity ansehen, sehen Sie, dass sich die Aktivität zuerst an Fragmente anfügt und dann super.onCreate() ausführt. Es gibt also keine Garantie, dass Ihr Code vor dem onCreate() Ihres Fragments ausgeführt wird. –

+0

Nun, ich würde es verstehen, wenn das Problem zu 100% reproduzierbar ist, da in der Tat onCreate() meines Fragments vor onCreate() der Aktivität aufgerufen wird. Ich denke, ich sollte die Frage bearbeiten. Es sollte umgekehrt werden. Warum wird onCreate() des Fragments nach activiys onCreate() aufgerufen, obwohl es in Activtys onCreate() ausgelöst wurde. – Zzokk

6

Der Rückruf Aktivitäten wird nicht nach den Fragmenten aufgerufen; Das Fragment wird während der Aktivität aufgerufen.

Initialise mAccounts vor super.onCreate() in Activity.onCreate()

+0

Danke für den Tipp. Es gibt definitiv mehrere Möglichkeiten, das Problem zu lösen. Die Frage ist, warum das Verhalten anders ist. Wie wird das onCreate() genau ausgelöst und warum passiert es manchmal nach onCreate() der Aktivität? – Zzokk

2

Dieser Fehler Aufruf kann durch Drehen auf "Dont't halten Aktivitäten" in Entwickleroptionen reproduzieren werden. Ich bin auf ein ähnliches Problem gestoßen und habe die Lösung von FunkTheMonk gelöst.

1

Kürzlich lief auf das Problem. Siehe Stapelverfolgung im unteren Bereich. Wie FunkTheMonk erklärt haben, ist der Absturz darauf zurückzuführen, dass Ihr angepasster onCreate() - Code in Ihrer Aktivität (direkt nach super.onCreate()) nach Ihrem angepassten onCreate() - Code in Ihrem Fragment ausgeführt wird (gleich danach) super.onCreate())

Wenn Sie wirklich Ihr Rückruf benötigen verheißungsvoll, nachdem die gesamte Aktivität des onCreate() ausgeführt werden, setzen Sie Ihre Code-Fragmente in onActivityCreated() statt onCreate()

Andernfalls wird die vorgenannte Bedingung geschehen wird, wenn Ihr Gedächtnis ist niedrig und die Aktivität wird recycelt.

Nach meiner Erfahrung, wenn MyActivity eine Absicht sendet, stürzt die App ab, sobald ich zu MyFragment zurückkehrt, indem ich die Zurück-Taste drücke.

Caused by: java.lang.NullPointerException 
    at MyFragment.onCreate(MyFragment.java:20) 
    at android.support.v4.app.Fragment.performCreate(Fragment.java:1939) 
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1029) 
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248) 
    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1230) 
    at android.support.v4.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:2037) 
    at android.support.v4.app.FragmentController.dispatchCreate(FragmentController.java:154) 
    at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:289) 
    at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:58) 
    at MyActivity.onCreate(MyActivity.java:129) 
    at android.app.Activity.performCreate(Activity.java:5248) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2162) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257) 
    at android.app.ActivityThread.access$800(ActivityThread.java:139) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:136) 
    at android.app.ActivityThread.main(ActivityThread.java:5086) 
    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:785) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 
    at dalvik.system.NativeStart.main(Native Method) 
0

Ich bin vielleicht zu spät, um noch zu antworten. Ich bin dies vor ein paar Tagen begegnet.Dies geschieht, wenn Sie dynamische Fragmente verwenden und im Layout das Fragment-Tag zum Anzeigen des Fragments verwenden. Verwenden Sie stattdessen ein Layout (vorzugsweise FrameLayout). Angenommen, Sie verwenden die Support-Fragment-Bibliothek.

Es ist einen Versuch wert.

Verwandte Themen