Chỉ cần rõ ràng, tôi đã đọc hàng chục câu hỏi SO hàng đầu về "IllegalStateException: Không thể thực hiện hành động này sau onSaveInstanceState" và tôi đã đọc bài đăng trên blog của Alex Lockwood về vấn đề này http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.htmlDialogFrag # show() từ một Fragment ném "IllegalStateException: Không thể thực hiện hành động này sau khi onSaveInstanceState"
Vì vậy, tôi không hỏi điều này một cách mù quáng.
Tôi có trường hợp sử dụng rất đơn giản mà không liên quan đến AsyncTask hoặc bất kỳ xử lý nền nào.
Tôi có Phân đoạn chứa nút. Trên onClickListener cho nút, tôi tạo một DialogFragment và hiển thị nó.
public final class OverviewFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.overview_fragment, container, false);
startNewGameButton = (Button) view.findViewById(R.id.buttonNewGame);
startNewGameButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final NewGameFragment dialogFrag = NewGameFragment.create(getApplication());
dialogFrag.show(getFragmentManager(), NewGameFragment.FRAGMENT_TAG);
}
});
}
[NewGameFragment]
public final class NewGameFragment extends DialogFragment {
public static final String FRAGMENT_TAG = "NewGameFragment";
private static final String MESSAGE = "message";
public static NewGameFragment create(Context context) {
final AppsPreferences prefs = new AppPreferences(context);
final int startOption = prefs.getGameStartOption();
final Bundle bundle = new Bundle();
bundle.putString(MESSAGE, getMessage(context, startOption));
final NewGameFragment fragment = new NewGameFragment();
fragment.setArguments(bundle);
return fragment;
}
@Override
public final Dialog onCreateDialog(Bundle savedInstanceState) {
final String message = getArguments().getString(MESSAGE);
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
.setTitle(R.string.progress_startGame_title)
.setMessage(message);
builder.setPositiveButton(R.string.progress_startGame_raceButton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new RaceAction().execute();
}
});
builder.setNegativeButton(R.string.progress_startGame_eventButton, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
new EventAction().execute();
}
});
final Dialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false); // Whether clicking outside the dialog closes the dialog.
return dialog;
}
}
[stacktrace]
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.void checkStateLoss()(SourceFile:1365)
at android.support.v4.app.FragmentManagerImpl.void enqueueAction(java.lang.Runnable,boolean)(SourceFile:1383)
at android.support.v4.app.BackStackRecord.int commitInternal(boolean)(SourceFile:636)
at android.support.v4.app.BackStackRecord.int commit()(SourceFile:615)
at android.support.v4.app.DialogFragment.void show(android.support.v4.app.FragmentManager,java.lang.String)(SourceFile:138)
at au.com.xandar.thegame.overview.OverviewFragment$1.void onClick(android.view.View)(SourceFile:160)
at android.view.View.performClick(View.java:4162)
at android.view.View$PerformClick.run(View.java:17082)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4867)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774)
at dalvik.system.NativeStart.main(Native Method)
NB Fragment và DialogFragment cả xuất phát từ sự ủng hộ-v4: 21.0.0
Tôi thấy điều này trên một loạt các thiết bị chạy 4.4. Nhưng ít nhất một trường hợp đã xảy ra trên Nexus 7 chạy 5.0.
Tôi đã không thể tự mình tái tạo. Không, ngay cả bằng cách giới thiệu một sự chậm trễ nhân tạo vào onClick và cố gắng xoay, quay lại, về nhà ứng dụng.
Vì vậy, kể từ khi FragmentTransaction
(ví DialogFrag#show()
) đang được tạo ra và cam kết về giao diện người dùng trực tiếp từ Chủ đề onClick()
, làm thế nào có thể các Fragment
đã đã tiến hành qua onSaveInstanceState()
?
Điều đó có nghĩa là tôi cần phải kiểm tra trạng thái của Vòng đời hoạt động ở đầu mỗi đầu vào của người dùng? - rất tệ (Vòng đời có nghĩa là xử lý điều đó cho tôi. Tôi không nên nhận dữ liệu nhập của người dùng nếu Hoạt động đã qua onPause()
)
Điều đó có nghĩa là tôi cần kiểm tra trạng thái của Vòng đời hoạt động trước khi mọi tuyên bố trong quá trình thực thi đầu vào của người dùng? - hỏng xấu !!
Tôi có thể làm gì để ngăn điều này xảy ra?
thông tin bổ sung:
Sau khi chạy trong môi trường tự nhiên trong vài ngày tôi khoát có thể nói rằng getChildFragmentManager()
không phải là giải pháp.
Không xảy ra cho các phiên bản Android sau:
- 4.4.2 90%
- 4.4.4 5%
- 5,0 5%
bài NewGameFragment lớp cũng –
Cố gắng di chuyển nó vào 'onActivityCreated' –
@BlazeTama di chuyển cái gì? Hiển thị hộp thoại? Điều đó đánh bại mục đích của việc hiển thị nó khi người dùng nhấp vào nút. – William