Ich habe eine FragmentActivity, die ein DialogFragment hostet.
Das DialogFragment führt Netzwerkanforderungen aus und verarbeitet die Facebook-Authentifizierung. Daher muss ich sie während der Rotation beibehalten.
Ich habe alle anderen Fragen zu diesem Problem gelesen, aber keine von ihnen hat das Problem tatsächlich gelöst.
Ich verwende putFragment und getFragment, um die Fragment-Instanz zu speichern und sie während der Neuerstellung der Aktivität erneut abzurufen.
Beim Aufruf von getFragment in onRestoreInstanceState wird jedoch immer eine Nullzeigerausnahme angezeigt. Ich möchte auch verhindern, dass der Dialog während der Rotation geschlossen wird, aber bisher kann ich die Instanz nicht einmal beibehalten.
Irgendwelche Ideen, was falsch läuft?
So sieht mein Code derzeit aus:
public class OKLoginActivity extends FragmentActivity implements OKLoginDialogListener
{
private OKLoginFragment loginDialog;
private static final String TAG_LOGINFRAGMENT = "OKLoginFragment";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FragmentManager fm = getSupportFragmentManager();
if(savedInstanceState == null)
{
loginDialog = new OKLoginFragment();
loginDialog.show(fm, TAG_LOGINFRAGMENT);
}
}
@Override
public void onSaveInstanceState(Bundle outState)
{
getSupportFragmentManager().putFragment(outState,TAG_LOGINFRAGMENT, loginDialog);
}
@Override
public void onRestoreInstanceState(Bundle inState)
{
FragmentManager fm = getSupportFragmentManager();
loginDialog = (OKLoginFragment) fm.getFragment(inState, TAG_LOGINFRAGMENT);
}
}
Dies ist die Ausnahme-Stack-Ablaufverfolgung:
02-01 16:31:13.684: E/AndroidRuntime(9739): FATAL EXCEPTION: main
02-01 16:31:13.684: E/AndroidRuntime(9739): java.lang.RuntimeException: Unable to start activity ComponentInfo{io.openkit.example.sampleokapp/io.openkit.OKLoginActivity}: java.lang.NullPointerException
02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3692)
02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread.access$700(ActivityThread.java:141)
02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1240)
02-01 16:31:13.684: E/AndroidRuntime(9739): at android.os.Handler.dispatchMessage(Handler.java:99)
02-01 16:31:13.684: E/AndroidRuntime(9739): at android.os.Looper.loop(Looper.java:137)
02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread.main(ActivityThread.java:5039)
02-01 16:31:13.684: E/AndroidRuntime(9739): at java.lang.reflect.Method.invokeNative(Native Method)
02-01 16:31:13.684: E/AndroidRuntime(9739): at java.lang.reflect.Method.invoke(Method.java:511)
02-01 16:31:13.684: E/AndroidRuntime(9739): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
02-01 16:31:13.684: E/AndroidRuntime(9739): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
02-01 16:31:13.684: E/AndroidRuntime(9739): at dalvik.system.NativeStart.main(Native Method)
02-01 16:31:13.684: E/AndroidRuntime(9739): Caused by: java.lang.NullPointerException
02-01 16:31:13.684: E/AndroidRuntime(9739): at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:528)
02-01 16:31:13.684: E/AndroidRuntime(9739): at io.openkit.OKLoginActivity.onRestoreInstanceState(OKLoginActivity.java:62)
02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.Activity.performRestoreInstanceState(Activity.java:910)
02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1131)
02-01 16:31:13.684: E/AndroidRuntime(9739): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2158)
super.onSaveInstanceState(outState)
in Ihrer überschriebenenonSaveInstanceState
Methode einen Aufruf hinzufügen .Antworten:
DialogFragment
Rufen Sie in IhremFragment.setRetainInstance(boolean)
mit dem Wert antrue
. Sie müssen das Fragment nicht manuell speichern, das Framework kümmert sich bereits um all dies. Wenn Sie dies aufrufen, wird verhindert, dass Ihr Fragment bei der Rotation zerstört wird und Ihre Netzwerkanforderungen nicht betroffen sind.Möglicherweise müssen Sie diesen Code hinzufügen, um zu verhindern, dass Ihr Dialogfeld bei der Rotation aufgrund eines Fehlers in der Kompatibilitätsbibliothek geschlossen wird:
@Override public void onDestroyView() { Dialog dialog = getDialog(); // handles https://code.google.com/p/android/issues/detail?id=17423 if (dialog != null && getRetainInstance()) { dialog.setDismissMessage(null); } super.onDestroyView(); }
quelle
Fragment.java
sagt dies übersetRetainInstance
: "Dies kann nur mit Fragmenten verwendet werden, die sich nicht im Backstack befinden." DialogFragment befindet sich definitiv im Backstackshow
. Weiß jemand, ob dieser Codekommentar einfach falsch ist?Einer der Vorteile der Verwendung
dialogFragment
gegenüber deralertDialogBuilder
bloßen Verwendung besteht genau darin, dass sich das Dialogfragment beim Drehen ohne Benutzereingriff automatisch neu erstellen kann.Wenn sich das Dialogfragment jedoch nicht selbst neu erstellt, ist es möglich, dass Sie überschreiben
onSaveInstanceState
, aber nicht aufrufensuper
:@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // <-- must call this if you want to retain dialogFragment upon rotation ... }
quelle
Dies ist eine bequeme Methode, bei der der Fix aus Antonytys Antwort verwendet wird:
public class RetainableDialogFragment extends DialogFragment { public RetainableDialogFragment() { setRetainInstance(true); } @Override public void onDestroyView() { Dialog dialog = getDialog(); // handles https://code.google.com/p/android/issues/detail?id=17423 if (dialog != null && getRetainInstance()) { dialog.setDismissMessage(null); } super.onDestroyView(); } }
Lassen Sie einfach
DialogFragment
diese Klasse erweitern und alles wird gut. Dies ist besonders praktisch, wenn Sie mehrereDialogFragments
in Ihrem Projekt haben, die alle dieses Update benötigen.quelle