Je rencontre un problème avec DialogFragment/getSupportFragmentManager/Android version 4.x
01-10 19:46:48.228: E/AndroidRuntime(9879): Java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
01-10 19:46:48.228: E/AndroidRuntime(9879): at Android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.Java:1314)
01-10 19:46:48.228: E/AndroidRuntime(9879): at Android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.Java:1325)
01-10 19:46:48.228: E/AndroidRuntime(9879): at Android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.Java:548)
01-10 19:46:48.228: E/AndroidRuntime(9879): at Android.support.v4.app.BackStackRecord.commit(BackStackRecord.Java:532)
01-10 19:46:48.228: E/AndroidRuntime(9879): at Android.support.v4.app.DialogFragment.show(DialogFragment.Java:127)
01-10 19:46:48.228: E/AndroidRuntime(9879): at com.v1.mypck.TermsAndConditions.showDialog(TermsAndConditions.Java:256)
01-10 19:46:48.228: E/AndroidRuntime(9879): at com.v1.mypck.TermsAndConditions.handleMessage(TermsAndConditions.Java:62)
01-10 19:46:48.228: E/AndroidRuntime(9879): at com.v1.mypck.TermsAndConditions$IncomingHandler.handleMessage(TermsAndConditions.Java:53)
01-10 19:46:48.228: E/AndroidRuntime(9879): at Android.os.Handler.dispatchMessage(Handler.Java:99)
01-10 19:46:48.228: E/AndroidRuntime(9879): at Android.os.Looper.loop(Looper.Java:137)
01-10 19:46:48.228: E/AndroidRuntime(9879): at Android.app.ActivityThread.main(ActivityThread.Java:4441)
01-10 19:46:48.228: E/AndroidRuntime(9879): at Java.lang.reflect.Method.invokeNative(Native Method)
01-10 19:46:48.228: E/AndroidRuntime(9879): at Java.lang.reflect.Method.invoke(Method.Java:511)
01-10 19:46:48.228: E/AndroidRuntime(9879): at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:784)
01-10 19:46:48.228: E/AndroidRuntime(9879): at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:551)
01-10 19:46:48.228: E/AndroidRuntime(9879): at dalvik.system.NativeStart.main(Native Method)
Dans le code ci-dessous, lorsque j'appuie sur, il essaie de terminer l'activité en cours et revient à l'activité précédente, il renvoie l'erreur ci-dessus.
Le code fonctionne bien sur les anciennes versions (antérieures à 4.x).
Quelqu'un peut-il me guider dans la bonne direction.
public class TermsAndConditions extends SherlockFragmentActivity implements LoaderManager.LoaderCallbacks<JSONObject>{
static final String TAG = "TermsAndConditions";
private static int titleResource;
private static int messageResource;
private IncomingHandler handler = null;
private static final int SHOW_NETWORK_DIALOG = 3;
static class IncomingHandler extends Handler {
private final WeakReference<TermsAndConditions> mTarget;
IncomingHandler(TermsAndConditions target) {
mTarget = new WeakReference<TermsAndConditions>(target);
}
@Override
public void handleMessage(Message msg) {
TermsAndConditions target = mTarget.get();
if (target != null) {
target.handleMessage(msg);
}
}
}
public void handleMessage(Message msg) {
switch (msg.what) {
case SHOW_NETWORK_DIALOG:
titleResource = R.string.msg_alert_no_network_title;
messageResource = R.string.msg_alert_no_network_message;
showDialog();
break;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.web_view);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportLoaderManager().initLoader(0, null, this);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case Android.R.id.home:
finish();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void loadViewData() {
//Logic to load content.
}
@Override
public Loader<JSONObject> onCreateLoader(int arg0, Bundle arg1) {
if (handler == null){
handler = new IncomingHandler(TermsAndConditions.this);
}
return new JsonLoader(this);
}
@Override
public void onLoadFinished(Loader<JSONObject> arg0, JSONObject jsonData) {
if(jsonDataObject==null || jsonDataObject.length()==0) {
handler.sendEmptyMessage(SHOW_NETWORK_DIALOG);
} else {
loadViewData();
}
}
@Override
public void onLoaderReset(Loader<JSONObject> arg0) {
if(jsonDataObject==null || jsonDataObject.length()==0) {
handler.sendEmptyMessage(SHOW_NETWORK_DIALOG);
} else {
loadViewData();
}
}
public static class JsonLoader extends AsyncTaskLoader<JSONObject> {
public JsonLoader(Context context) {
super(context);
}
@Override
protected void onStartLoading() {
if (jsonDataObject != null) {
deliverResult(jsonDataObject);
}
if (takeContentChanged() || jsonDataObject == null) {
forceLoad();
}
}
@Override
public JSONObject loadInBackground() {
try {
return response.getJSONObject("result");
} catch (JSONException e) {
return null;
} catch (Throwable e) {
return null;
}
}
@Override
public void deliverResult(JSONObject newJsonData) {
if (isReset()) {
if (jsonDataObject != null) {
onReleaseResources(jsonDataObject);
}
}
JSONObject oldData = jsonDataObject;
jsonDataObject = newJsonData;
if (isStarted()) {
super.deliverResult(jsonDataObject);
}
if (oldData != null) {
onReleaseResources(oldData);
}
}
@Override
protected void onStopLoading() {
cancelLoad();
}
@Override public void onCanceled(JSONObject jsonData) {
super.onCanceled(jsonData);
onReleaseResources(jsonData);
}
@Override protected void onReset() {
super.onReset();
onStopLoading();
if (jsonDataObject != null) {
onReleaseResources(jsonDataObject);
jsonDataObject = null;
}
}
protected void onReleaseResources(JSONObject jsonData) {
jsonData = null;
}
}
public static class MyAlertDialogFragment extends DialogFragment {
public static MyAlertDialogFragment newInstance(int title) {
MyAlertDialogFragment frag = new MyAlertDialogFragment();
Bundle args = new Bundle();
args.putInt("title", title);
frag.setArguments(args);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
return new AlertDialog.Builder(getActivity())
.setTitle(title)
.setMessage(messageResource)
.setPositiveButton(R.string.alert_dialog_ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
}
)
.create();
}
}
public void showDialog() {
DialogFragment newFragment = MyAlertDialogFragment.newInstance(titleResource);
newFragment.show(getSupportFragmentManager(), "my_dialog");
}
}
Voici la réponse dans un autre fil:
ici aussi:
Rafraîchir mon fragment ne fonctionne pas comme je le pensais
Voici un exemple pour résoudre ce problème:
DialogFragment loadingDialog = createDialog();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(loadingDialog, "loading");
transaction.commitAllowingStateLoss();
J'ai le même problème et j'ai changé le code comme ci-dessous
newFragment.show(transactionFragment, "dialog");
à:
transactionFragment.add(Android.R.id.content, newFragment).addToBackStack(null).commitAllowingStateLoss();
le code terminé fonctionne bien pour moi en tant que soufflet, j'espère que l'aide
FragmentTransaction transactionFragment = getActivity().getSupportFragmentManager().beginTransaction();
DialogPageListFragment newFragment = new DialogPageListFragment();
transactionFragment.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
newFragment.setArguments(extras);
transactionFragment.add(Android.R.id.content, newFragment).addToBackStack(null).commitAllowingStateLoss();
Le gestionnaire qui répond au HandleMessage est probablement associé à une activité détruite.
c'est-à-dire: si vous faites pivoter l'écran, l'ancienne activité détruite gérera le message, puis vous appellerez showDialog, et l'exception sera levée:
Vous créez une boîte de dialogue après que l'ancienne activité détruite a appelé son onSaveInstanceState.
Essayez de remplacer le rappel, par la nouvelle activité créée, pour vous assurer que vous créez la boîte de dialogue toujours dans l'activité vivante.
Si vous ne faites pas de rotation, placez un indicateur sur onSaveInstance comme "enregistrer" et désactivez-le sur onRestoreInstance. Dans votre méthode handleMessage, si l'indicateur "save" est activé, n'affichez pas la boîte de dialogue, activez simplement un autre indicateur indiquant que la boîte de dialogue doit être créée sur onResume. Ensuite, sur la méthode onResume, vérifiez si au milieu de ce processus, vous devez créer la boîte de dialogue, si oui, affichez-la sur la méthode onResume.
fragmentView.post(() -> {
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
YourDialog yourDialog = YourDialog.newInstance();
yourDialog.show(ft, "text_data");
});
Le but de la méthode post () dans ce cas est d'attendre la fin de onResume () de l'activité ou du fragment. Cela fonctionne si vous souhaitez afficher DialogFragment from Fragment., F.e. lorsque vous souhaitez afficher votre boîte de dialogue après la fermeture d'une boîte de dialogue système.
J'étais confronté au même problème lors du post-retardement de Runnables handler.postDelayed (Runnable runnable, long delay).
J'ai résolu le problème de cette façon:
réponse trop tardive mais peut être la bonne réponse. J'ai créé une classe parente et un fragment de dialogue en part
public class BaseDialogFragment extends DialogFragment {
@Override
public void show(FragmentManager manager, String tag) {
try {
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag).addToBackStack(null);
ft.commitAllowingStateLoss();
} catch (IllegalStateException e) {
Log.d("ABSDIALOGFRAG", "Exception", e);
}
}
boolean mIsStateAlreadySaved = false;
boolean mPendingShowDialog = false;
@Override
public void onResume() {
onResumeFragments();
super.onResume();
}
public void onResumeFragments(){
mIsStateAlreadySaved = false;
if(mPendingShowDialog){
mPendingShowDialog = false;
showSnoozeDialog();
}
}
@Override
public void onPause() {
super.onPause();
mIsStateAlreadySaved = true;
}
private void showSnoozeDialog() {
if(mIsStateAlreadySaved){
mPendingShowDialog = true;
}else{
FragmentManager fm = getFragmentManager();
BaseDialogFragment snoozeDialog = new BaseDialogFragment();
snoozeDialog.show(fm, "BaseDialogFragment");
}
}
}
Vous pouvez vérifier si l'activité actuelle estActive () et uniquement dans ce cas démarrer la transaction de fragment de DialogFragment. J'ai eu un problème similaire et cette vérification a résolu mon cas.
onPostResume () utilisez la méthode post resume pour faire votre travail .. Je pense que vous appelez la méthode show dialog dans onRestart ou onResume, alors évitez-la et utilisez onPostResume () pour afficher votre dialogue.
Ça marche:
CheckinSuccessDialog dialog = new CheckinSuccessDialog();
//dialog.show(getSupportFragmentManager(), null);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(dialog, null);
ft.commitAllowingStateLoss();
Mais mais toujours mauvais, car l'erreur "L'activité a été détruite"
ava.lang.IllegalStateException: Activity has been destroyed fragmentTransaction.commitAllowingStateLoss();
Donc ma solution est d'ajouter check if (!isFinishing()&&!isDestroyed())
CheckinSuccessDialog fragment = CheckinSuccessDialog.newInstance();
if (fragment instanceof DialogFragment) {
DialogFragment dialog = (DialogFragment) fragment;
if (!dialog.isAdded()) {
fragmentTransaction.add(dialog,
CheckinSuccessDialog.class.getName());
if (!isFinishing()&&!isDestroyed()) {
fragmentTransaction.commitAllowingStateLoss();
}
}
en cas de licenciement:
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
Fragment fragment = getSupportFragmentManager().findFragmentByTag(CheckinSuccessDialog.class.getName());
if (fragment != null && fragment instanceof DialogFragment) {
DialogFragment dialog = (DialogFragment) fragment;
dialog.dismiss();
if (!isFinishing()&&!isDestroyed()) {
fragmentTransaction.commitAllowingStateLoss();
}
}