В моем onActivityResult есть следующий код для моего фрагмента:
onActivityResult(int requestCode, int resultCode, Intent data){
//other code
ProgressFragment progFragment = new ProgressFragment();
progFragment.show(getActivity().getSupportFragmentManager(), PROG_DIALOG_TAG);
// other code
}
Однако я получаю следующую ошибку:
Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
Кто-нибудь знает, что происходит, или как я могу это исправить? Следует отметить, что я использую пакет поддержки Android.
android
android-fragments
android-dialogfragment
Куртис Нусбаум
источник
источник
onResumeFragments()
этого не существует вActivity
классе. Если вы используете базовыйActivity
, вам следует использоватьonPostResume()
вместо него.РЕДАКТИРОВАТЬ: Не ошибка, а скорее недостаток в структуре фрагментов. Лучший ответ на этот вопрос дает @Arcao выше.
---- Оригинальный пост ----
На самом деле это известная ошибка в пакете поддержки (правка: на самом деле это не ошибка. См. Комментарий @ alex-lockwood). Опубликованная работа в комментариях к отчету об ошибке заключается в изменении источника DialogFragment следующим образом:
public int show(FragmentTransaction transaction, String tag) { return show(transaction, tag, false); } public int show(FragmentTransaction transaction, String tag, boolean allowStateLoss) { transaction.add(this, tag); mRemoved = false; mBackStackId = allowStateLoss ? transaction.commitAllowingStateLoss() : transaction.commit(); return mBackStackId; }
Обратите внимание, что это гигантский взлом. На самом деле я просто сделал свой собственный фрагмент диалога, который я мог зарегистрировать из исходного фрагмента. Когда этот другой фрагмент диалога сделал что-то (например, был отклонен), он сказал всем слушателям, что он уходит. У меня так получилось:
public static class PlayerPasswordFragment extends DialogFragment{ Player toJoin; EditText passwordEdit; Button okButton; PlayerListFragment playerListFragment = null; public void onCreate(Bundle icicle){ super.onCreate(icicle); toJoin = Player.unbundle(getArguments()); Log.d(TAG, "Player id in PasswordFragment: " + toJoin.getId()); } public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle icicle){ View v = inflater.inflate(R.layout.player_password, container, false); passwordEdit = (EditText)v.findViewById(R.id.player_password_edit); okButton = (Button)v.findViewById(R.id.ok_button); okButton.setOnClickListener(new View.OnClickListener(){ public void onClick(View v){ passwordEntered(); } }); getDialog().setTitle(R.string.password_required); return v; } public void passwordEntered(){ //TODO handle if they didn't type anything in playerListFragment.joinPlayer(toJoin, passwordEdit.getText().toString()); dismiss(); } public void registerPasswordEnteredListener(PlayerListFragment playerListFragment){ this.playerListFragment = playerListFragment; } public void unregisterPasswordEnteredListener(){ this.playerListFragment = null; } }
Итак, теперь у меня есть способ уведомлять PlayerListFragment, когда что-то происходит. Обратите внимание, что очень важно, чтобы вы вызывали unregisterPasswordEnteredListener соответствующим образом (в приведенном выше случае, когда PlayerListFragment «исчезает»), иначе этот фрагмент диалога может попытаться вызвать функции зарегистрированного слушателя, когда этот слушатель больше не существует.
источник
show()
и перехватитеIllegalStateException
.onActivityResult()
! Вместо этого попробуйте это решение: stackoverflow.com/questions/16265733/…onPostResume
иonResumeFragments
является относительно новым дополнением к библиотеке поддержки.Комментарий, оставленный @Natix представляет собой краткий который некоторые люди, возможно, удалили.
Самое простое решение этой проблемы - вызвать super.onActivityResult () ПЕРЕД запуском собственного кода. Это работает независимо от того, используете ли вы библиотеку поддержки или нет, и поддерживает согласованность поведения в вашей деятельности.
Есть:
Чем больше я читаю об этом, тем больше безумных хаков я видел.
Если вы все еще сталкиваетесь с проблемами, то вам стоит проверить проблему Алекса Локвуда .
источник
super.onActivityResult(requestCode, resultCode, data)
перед любым кодом, это устранило мою проблему. Но при добавлении наследования или переопределении значения по умолчанию onActivityResult мы должны обрабатывать onStart / onResume вручнуюЯ считаю, что это ошибка Android. В основном Android вызывает onActivityResult в неправильный момент жизненного цикла активности / фрагмента (до onStart ()).
Об ошибке сообщается по адресу https://issuetracker.google.com/issues/36929762.
Я решил это, в основном сохранив намерение как параметр, который я позже обработал в onResume ().
[РЕДАКТИРОВАТЬ] В настоящее время существуют лучшие решения этой проблемы, которые не были доступны еще в 2012 году. См. Другие ответы.
источник
onActivityResult()
это называлось раньшеonResume()
РЕДАКТИРОВАТЬ: еще один вариант и, возможно, лучший (или, по крайней мере, то, что ожидает библиотека поддержки ...)
Если вы используете DialogFragments с библиотекой поддержки Android, вы должны использовать подкласс FragmentActivity. Попробуйте следующее:
onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, intent); //other code ProgressFragment progFragment = new ProgressFragment(); progFragment.show(getActivity().getSupportFragmentManager(), PROG_DIALOG_TAG); // other code }
Я взглянул на источник FragmentActivity, и похоже, что он вызывает внутренний диспетчер фрагментов, чтобы возобновить фрагменты без потери состояния.
Я нашел решение, которого здесь нет. Я создаю обработчик и запускаю фрагмент диалога в обработчике. Итак, немного отредактируем свой код:
onActivityResult(int requestCode, int resultCode, Intent data) { //other code final FragmentManager manager = getActivity().getSupportFragmentManager(); Handler handler = new Handler(); handler.post(new Runnable() { public void run() { ProgressFragment progFragment = new ProgressFragment(); progFragment.show(manager, PROG_DIALOG_TAG); } }); // other code }
Мне это кажется чище и менее хакерским.
источник
Thread#sleep()
.super.onActivityResult()
- это самое простое рабочее решение, и, вероятно, это должен быть принятый ответ! Я случайно заметил пропавший супер-вызов и был приятно удивлен, что его добавление просто сработало. Это позволило мне удалить один из старых приемов, упомянутых на этой странице (сохранение диалогового окна во временную переменную и его отображениеonResume()
).onActivityResult()
что не возвращается никакого значения, которое указывает, обработали ли фрагменты результат.Есть два метода DialogFragment show () -
show(FragmentManager manager, String tag)
иshow(FragmentTransaction transaction, String tag)
.Если вы хотите использовать версию метода FragmentManager (как в исходном вопросе), простое решение - переопределить этот метод и использовать commitAllowingStateLoss:
public class MyDialogFragment extends DialogFragment { @Override public void show(FragmentManager manager, String tag) { FragmentTransaction ft = manager.beginTransaction(); ft.add(this, tag); ft.commitAllowingStateLoss(); } }
Отмена
show(FragmentTransaction, String)
этот способ не так просто, потому что он также должен изменить некоторые внутренние переменные в исходном коде DialogFragment, поэтому я бы не рекомендовал его - если вы хотите использовать этот метод, попробуйте предложения в принятом ответе (или комментарии из Джеффри Блаттман).Есть некоторый риск в использовании commitAllowingStateLoss - в документации указано: «Как и commit (), но позволяет выполнить фиксацию после сохранения состояния действия. Это опасно, потому что фиксация может быть потеряна, если действие необходимо позже восстановить из его состояния. , поэтому это следует использовать только в тех случаях, когда состояние пользовательского интерфейса может неожиданно измениться для пользователя ".
источник
Вы не можете отобразить диалог после того, как прикрепленное действие вызвало свой метод onSaveInstanceState (). Очевидно, что onSaveInstanceState () вызывается перед onActivityResult (). Таким образом, вы должны показать свой диалог в этом методе обратного вызова OnResumeFragment (), вам не нужно переопределять метод show () DialogFragment. Надеюсь, что это поможет вам.
источник
Я придумал третье решение, частично основанное на решении hmt. По сути, создайте ArrayList из DialogFragments, который будет отображаться при onResume ();
ArrayList<DialogFragment> dialogList=new ArrayList<DialogFragment>(); //Some function, like onActivityResults { DialogFragment dialog=new DialogFragment(); dialogList.add(dialog); } protected void onResume() { super.onResume(); while (!dialogList.isEmpty()) dialogList.remove(0).show(getSupportFragmentManager(),"someDialog"); }
источник
onActivityResult () выполняется перед onResume (). Вам нужно создать свой пользовательский интерфейс в onResume () или более поздней версии.
Используйте логическое значение или что-то еще, что вам нужно, чтобы сообщить, что результат вернулся между обоими этими методами.
... Это оно. Просто.
источник
Я знаю, что на этот вопрос был дан ответ довольно давно ... но есть гораздо более простой способ сделать это, чем некоторые другие ответы, которые я видел здесь ... В моем конкретном случае мне нужно было показать DialogFragment из фрагментов onActivityResult () метод.
Это мой код для этого, и он прекрасно работает:
DialogFragment myFrag; //Don't forget to instantiate this FragmentTransaction trans = getActivity().getSupportFragmentManager().beginTransaction(); trans.add(myFrag, "MyDialogFragmentTag"); trans.commitAllowingStateLoss();
Как упоминалось в некоторых других сообщениях, фиксация с потерей состояния может вызвать проблемы, если вы не будете осторожны ... в моем случае я просто отображал сообщение об ошибке пользователю с кнопкой, чтобы закрыть диалоговое окно, поэтому, если состояние того потеряно, это не имеет большого значения.
Надеюсь это поможет...
источник
Это старый вопрос, но я решил простейшим способом, думаю:
getActivity().runOnUiThread(new Runnable() { @Override public void run() { MsgUtils.toast(getString(R.string.msg_img_saved), getActivity().getApplicationContext()); } });
источник
Это происходит потому, что когда вызывается #onActivityResult (), родительское действие уже вызывает #onSaveInstanceState ()
Я бы использовал Runnable, чтобы «сохранить» действие (показать диалог) в #onActivityResult (), чтобы использовать его позже, когда действие будет готово.
При таком подходе мы гарантируем, что действие, которое мы хотим, всегда будет работать.
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == YOUR_REQUEST_CODE) { mRunnable = new Runnable() { @Override public void run() { showDialog(); } }; } else { super.onActivityResult(requestCode, resultCode, data); } } @Override public void onStart() { super.onStart(); if (mRunnable != null) { mRunnable.run(); mRunnable = null; } }
источник
Самое чистое решение, которое я нашел:
@Override public void onActivityResult(final int requestCode, final int resultCode, final Intent data) { new Handler().post(new Runnable() { @Override public void run() { onActivityResultDelayed(requestCode, resultCode, data); } }); } public void onActivityResultDelayed(int requestCode, int resultCode, Intent data) { // Move your onActivityResult() code here. }
источник
Я получил эту ошибку во время работы
.show(getSupportFragmentManager(), "MyDialog");
..show(getSupportFragmentManager().beginTransaction(), "MyDialog");
Сначала попробуйте .Если все еще не работает, этот пост ( Показать DialogFragment из onActivityResult ) помогает мне решить проблему.
источник
По-другому:
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case Activity.RESULT_OK: new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message m) { showErrorDialog(msg); return false; } }).sendEmptyMessage(0); break; default: super.onActivityResult(requestCode, resultCode, data); } } private void showErrorDialog(String msg) { // build and show dialog here }
источник
просто позвоните
super.onActivityResult(requestCode, resultCode, data);
перед обработкой фрагментаисточник
Как вы все знаете, эта проблема возникает из-за того, что onActivityResult () вызывает перед onstart (), поэтому просто вызовите onstart () при запуске в onActivityResult (), как я сделал в этом коде
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { onStart(); //write you code here }
источник