web-dev-qa-db-de.com

java.lang.IllegalStateException: Diese Aktion kann nach onSaveInstanceState mit DialogFragment nicht ausgeführt werden

Ich habe ein Problem mit 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)

Wenn ich im folgenden Code auf "Zurück" drücke, wird versucht, die aktuelle Aktivität zu beenden und zur vorherigen Aktivität zurückzukehren, die über "Fehler" ausgelöst wird.

Code funktioniert gut mit älteren Versionen (vor 4.x).

Kann mich jemand in die richtige Richtung führen?.

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

Hier ist die Antwort in einem anderen Thread:

Aktionen in onActivityResult und "Fehler Kann diese Aktion nach onSaveInstanceState nicht ausführen"

auch hier:

Das Auffrischen meines Fragments funktioniert nicht so, wie ich es mir vorgestellt habe

Dies ist ein Beispiel zur Lösung dieses Problems:

DialogFragment loadingDialog = createDialog();

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                    transaction.add(loadingDialog, "loading");
                    transaction.commitAllowingStateLoss();  
48
Khaled Annajar

Ich habe das gleiche Problem und den Code wie folgt geändert

newFragment.show(transactionFragment, "dialog");

zu:

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

der fertige Code funktioniert gut für mich, hoffe das hilft

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();
8
Tran Khanh Tung

Wahrscheinlich ist der Handler, der auf die HandleMessage antwortet, einer zerstörten Aktivität zugeordnet.

wenn Sie den Bildschirm drehen, wird die Nachricht von der alten zerstörten Aktivität verarbeitet, und Sie rufen showDialog auf, und die Ausnahme wird ausgelöst:

Sie erstellen einen Dialog, nachdem die alte zerstörte Aktivität ihren onSaveInstanceState aufgerufen hat.

Ersetzen Sie den Rückruf durch die neu erstellte Aktivität, um sicherzustellen, dass Sie das Dialogfeld immer in der aktiven Aktivität erstellen.


Wenn Sie nicht rotieren, setzen Sie ein Flag auf onSaveInstance, z. B. "save", und deaktivieren Sie es auf onRestoreInstance. Wenn in Ihrer handleMessage-Methode das Flag "saving" (Speichern) aktiviert ist, wird das Dialogfeld nicht angezeigt. Aktivieren Sie einfach ein anderes Flag, das angibt, dass das Dialogfeld in onResume erstellt werden muss. Überprüfen Sie dann bei der onResume-Methode, ob Sie während dieses Vorgangs das Dialogfeld erstellen sollten. Wenn ja, zeigen Sie es bei der onResume-Methode an.

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

In diesem Fall besteht das Ziel der post () -Methode darin, zu warten, bis onResume () von Activity oder Fragment beendet ist. Es funktioniert, wenn Sie DialogFragment aus Fragment anzeigen möchten., Z. wenn Sie Ihren Dialog nach dem Schließen eines Systemdialogs anzeigen möchten.

4
Maksim

Ich hatte das gleiche Problem, als ich Runnables handler.postDelayed (Runnable runnable, long delayed) verzögerte.

Ich habe das Problem folgendermaßen gelöst:

  1. In onSaveInstanceState storniere ich die verzögerten Aufgaben
  2. In onRestoreInstanceState erstelle ich die Aufgabe neu, wenn bei der Zerstörung der Aktivität verzögerte Aufgaben aufgetreten sind
2
user2832184

zu späte Antwort kann aber die richtige Antwort sein. Ich habe eine übergeordnete Klasse erstellt und ein Dialogfragment wird daraus erweitert

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

}

1
mostafa hashim

Sie können prüfen, ob die aktuelle AktivitätActive () ist, und nur in diesem Fall die Fragmenttransaktion von DialogFragment starten. Ich hatte ein ähnliches Problem und diese Überprüfung löste meinen Fall.

0
box

onPostResume () Verwenden Sie die Post-Resume-Methode, um Ihre Arbeit zu erledigen. Ich glaube, Sie rufen die Show-Dialog-Methode in onRestart oder onResume auf. Vermeiden Sie dies und verwenden Sie onPostResume (), um dies zu zeigen Ihr Dialog.

0
Vikas Kumbhar

Es klappt:

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

Aber trotzdem schlimm, da bekam Fehler "Aktivität wurde zerstört"

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

Also meine Lösung ist add 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();
                    }
                }

bei Entlassung:

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