android illegalstateexception android-dialogfragment android-support-library

android - java.lang.IllegalStateException: No se puede realizar esta acción después de onSaveInstanceState con DialogFragment



android-dialogfragment android-support-library (10)

Aquí está la respuesta en otro hilo:

Acciones en onActivityResult y "Error no se puede realizar esta acción después de onSaveInstanceState"

también aquí:

Refrescar mi fragmento no funciona como pensé que debería

Este es un ejemplo para resolver este problema:

DialogFragment loadingDialog = createDialog(); FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.add(loadingDialog, "loading"); transaction.commitAllowingStateLoss();

Estoy enfrentando un problema con DialogFragment / getSupportFragmentManager / Android versión 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)

En el código siguiente, cuando presiono hacia atrás, intenta finalizar la actividad actual y volver a la actividad anterior arroja el error anterior.

El código funciona bien en versiones anteriores (anteriores a 4.x).

¿Alguien puede guiarme en la dirección correcta?

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"); } }


En la Actividad , antes de mostrar el diálogo puede hacer algo como esto

getSupportFragmentManager().executePendingTransactions();

Esto funcionó para mí.


Estaba enfrentando el mismo problema cuando pospuse Runnables handler.postDelayed (ejecutable Runnable, long delay).

He resuelto el problema de esta manera:

  1. En onSaveInstanceState, cancelo las tareas retrasadas
  2. En onRestoreInstanceState recreé la tarea si hubo tareas retrasadas cuando se destruyó la actividad

Funciona:

CheckinSuccessDialog dialog = new CheckinSuccessDialog(); //dialog.show(getSupportFragmentManager(), null); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.add(dialog, null); ft.commitAllowingStateLoss();

Pero aún así es malo, porque obtuve el error "La actividad se ha destruido"

ava.lang.IllegalStateException: Activity has been destroyed fragmentTransaction.commitAllowingStateLoss();

Entonces mi solución es agregar verificación 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 despedir:

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(); } }


Probablemente, el controlador que responde al HandleMessage está asociado a una actividad destruida.

es decir: si gira la pantalla, la antigua actividad destruida manejará el mensaje, luego llamará a showDialog y se lanzará la excepción:

Está creando un cuadro de diálogo después de que la antigua actividad destruida lo haya llamado onSaveInstanceState.

Intente reemplazar la devolución de llamada, con la nueva actividad creada, para asegurarse de que está creando el diálogo siempre en la actividad activa.

Si no está girando, coloque una bandera en Save Instance como "guardar" y desactívelo en onRestoreInstance. En el método handleMessage, si el indicador "guardar" está activado, no muestre el diálogo, solo active otro indicador que indique que el diálogo debe crearse en onResume. Luego, en el método onResume, compruebe si en medio de ese proceso, debe crear el cuadro de diálogo; si es así, muéstrelo en el método onResume.


Puede verificar si la actividad actual es Activa () y solo en ese caso iniciar la transacción de fragmento de DialogFragment. Tuve un problema similar y este control resolvió mi caso.


Tengo el mismo problema y cambié el código como abajo

newFragment.show(transactionFragment, "dialog");

a:

transactionFragment.add(android.R.id.content, newFragment).addToBackStack(null).commitAllowingStateLoss();

el código completo funciona bien para mí como abajo, espero que ayuden

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();


respuesta demasiado tardía, pero puede ser la respuesta correcta. Hice una clase para padres y el fragmento de diálogo se extiende desde

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"); } }

}


onPostResume () usa el método de reanudación de la publicación para hacer su trabajo. Creo que está llamando al método de diálogo show en onRestart o onResume, así que evítelo y use onPostResume () para mostrar su diálogo.


fragmentView.post(() -> { FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction(); YourDialog yourDialog = YourDialog.newInstance(); yourDialog.show(ft, "text_data"); });

El objetivo del método post () en este caso es esperar mientras finaliza OnResume () de Activity o Fragment. Funciona si desea mostrar DialogFragment from Fragment., Fe cuando desea mostrar su cuadro de diálogo después de que se desactive el diálogo del sistema.