14

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%
+0

bài NewGameFragment lớp cũng –

+0

Cố gắng di chuyển nó vào 'onActivityCreated' –

+0

@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

Trả lời

3

OK, như xa như tôi có thể cho biết đây là một bug trong AOSP vì tôi cũng đã nhìn thấy một ví dụ này từ ngăn xếp Android thuần túy (tức là không có gì của mã của tôi cả).Vì vậy, có vẻ như có vấn đề về luồng trong vòng đời Hoạt động/Phân đoạn trong đó chuỗi giao diện người dùng có thể được ưu tiên trả lời một nút bấm SAU Hoạt động/Phân đoạn đã lưu trạng thái của nó.

Công việc của tôi xung quanh đó đã được 100% thành công cho đến nay là để bắt IllegalStateException và sắp xếp chương trình thoại cho thời gian tới các Hoạt động/Fragment trở nên tích cực sử dụng một PauseHandler https://stackoverflow.com/a/25322330/493682

+0

Xin chào, gặp phải vấn đề tương tự. Bạn đã đăng nhập vào bộ theo dõi vấn đề AOSP chưa? – hidro

+0

Đã thêm liên kết để trả lời – William

+0

Cảm ơn, tôi đã kiểm tra một loạt các lỗi AOSP tương tự trước đó. Đáng ngạc nhiên là tất cả chúng đều được đánh dấu là lỗi thời. – hidro

Các vấn đề liên quan