web-dev-qa-db-ja.com

java.lang.IllegalStateException:DialogFragmentでonSaveInstanceStateの後にこのアクションを実行できません

DialogFragment/getSupportFragmentManager/Androidバージョン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)

下のコードでは、現在のアクティビティを終了し、前のアクティビティに戻り、上記のエラーがスローされます。

コードは古いバージョン(4.xより前)で正常に機能します。

誰かが正しい方向に私を導くことができます。

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

別のスレッドでの答えは次のとおりです。

onActivityResultのアクションおよび「エラーがonSaveInstanceStateの後にこのアクションを実行できません」

ここもまた:

フラグメントを更新すると思ったように動作しません

これはこの問題を解決する例です:

DialogFragment loadingDialog = createDialog();

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

同じ問題が発生し、コードを次のように変更しました

newFragment.show(transactionFragment, "dialog");

に:

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

完成したコードは、私にとって以下のようにうまく機能します。

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

おそらく、HandleMessageに応答しているハンドラーは、破棄されたアクティビティに関連付けられています。

つまり、画面を回転させると、破棄された古いアクティビティがメッセージを処理し、showDialogを呼び出して例外がスローされます:

古い破壊されたアクティビティが彼のonSaveInstanceStateを呼び出した後、ダイアログを作成しています。

コールバックを新しく作成したアクティビティに置き換えて、常にアライブアクティビティでダイアログを作成していることを確認してください。


回転していない場合は、onSaveInstanceに「saving」などのフラグを設定し、onRestoreInstanceで無効にします。 handleMessageメソッドで、フラグ「saving」がオンの場合、ダイアログを表示せず、onResumeでダイアログを作成する必要があることを示す別のフラグをオンにします。次に、onResumeメソッドで、そのプロセスの途中でダイアログを作成する必要があるかどうかを確認します。作成する場合は、onResumeメソッドでダイアログを表示します。

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

この場合のpost()メソッドの目標は、ActivityまたはFragmentのonResume()が完了するまで待つことです。 Fragment。、f.eからDialogFragmentを表示したい場合に機能します。システムダイアログが閉じられた後にダイアログを表示する場合。

4
Maksim

Runnables handler.postDelayed(Runnable runnable、long delayed)を遅延させてポストするときに同じ問題に直面していました。

私はこの方法で問題を解決しました:

  1. OnSaveInstanceStateで遅延タスクをキャンセルします
  2. OnRestoreInstanceStateで、アクティビティが破棄されたときに遅延タスクがあった場合、タスクを再作成します
2
user2832184

遅すぎる答えですが、正しい答えかもしれません。私は親クラスを作成し、ダイアログフラグメントはそれから拡張します

 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

現在のアクティビティがActive()かどうかを確認でき、その場合のみDialogFragmentのフラグメントトランザクションを開始できます。同様の問題が発生したため、このチェックでケースを解決しました。

0
box

onPostResume() post resumeメソッドを使用して作業を行います。onRestartまたはonResumeでshow dialogメソッドを呼び出していると思うので、回避してonPostResume()を使用して表示してくださいあなたのダイアログ。

0
Vikas Kumbhar

できます:

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

しかし、「アクティビティが破棄されました」というエラーが発生したため、依然として悪い

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

だから私の解決策はチェック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();
                    }
                }
_

解雇時:

_  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