2012-08-24 40 views
42

Triển khai ứng dụng mà người dùng có thể đăng nhập Tôi có tình huống sau: Nếu người dùng đăng nhập thực hiện hành động khác, hãy bắt đầu hoạt động đăng nhập cho kết quả và nếu kết quả là Activity.RESULT_OK thực hiện hành động.Hành động trong onActivityResult và "Lỗi Không thể thực hiện thao tác này sau khi onSaveInstanceState"

Vấn đề của tôi là hành động để phí phạm là để hiển thị một DialogFragment, nhưng gọi

DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel); 
newFragment.show(ft, "dialog") 

trong callback onActivityResult ném một ngoại lệ:

Caused by: java.lang.IllegalStateException: 
Can not perform this action after onSaveInstanceState 

Vì vậy, làm thế nào tôi có thể giải quyết này? Tôi đang nghĩ đến trong việc nâng cao một lá cờ đó và hiển thị hộp thoại ở mặt onResume nhưng tôi thấy giải pháp này một chút bẩn

Edit: Nhập mã hơn (Im sau ví dụ này cho thấy DialogFragment

Khi hành động là theo yêu cầu của người sử dụng:

... 
if (!user.isLogged()){ 
startActivityForResult(new Intent(cnt, Login.class), REQUEST_LOGIN_FOR_COMMENT); 
} 

trong cùng một đoạn

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    super.onActivityResult(requestCode, resultCode, data); 
    if (requestCode == REQUEST_LOGIN_FOR_COMMENT && resultCode == Activity.RESULT_OK) { 
     FragmentTransaction ft = getFragmentManager().beginTransaction(); 
     DialogFragment newFragment = MyDialogFragment.newInstance(); 
     newFragment.show(ft, "dialog") 
    } 
} 

Và nếu người dùng đăng nhập hoạt động Login gọi;

setResult(Activity.RESULT_OK); 
finish(); 
+0

tôi nghĩ bạn nên đăng toàn bộ mã. Có vẻ như bạn đang cố gắng hiển thị hộp thoại sau khi bật – nandeesh

+0

Đã chỉnh sửa câu hỏi: D – Addev

+1

Kiểm tra http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html để hiểu tại sao điều này xảy ra – Maragues

Trả lời

94

Điều tốt nhất mà tôi đã đưa ra là không sử dụng .show() nhưng thay vì làm điều này.

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

Mặc dù nó làm việc cho tôi, tôi cảm thấy không an toàn vì chúng tôi đã bỏ qua 2 biến: mDismissed = false; mShownByMe = true; Các biến trên đang được sửa đổi trong chức năng hiển thị ban đầu. –

+2

cảm ơn bạn, commitAllowingStateLoss đã giải quyết vấn đề cho tôi –

+0

mDismissed và mShowByMe dường như là các biến đặc biệt để theo dõi xem hộp thoại có được hiển thị/ẩn bởi các cuộc gọi bên ngoài hay không. Nói cách khác, họ bù đắp cho chính xác loại điều này. –

9

Đây là giải pháp hữu ích cho tôi.

private void alert(final String message) { 
    Handler handler = new Handler(Looper.getMainLooper()); 
    handler.post(new Runnable() { 
     public void run() { 
      AlertDialogFragment alertDialogFragment = AlertDialogFragment.newInstance(message); 
      alertDialogFragment.show(getFragmentManager(), ALERT_DIALOG_FRAGMENT); 
     } 
    });   
} 
4

Nếu sử dụng một DialogFragment, điều duy nhất mà làm việc cho tôi là để bỏ qua những Fragment với dissmissAllowingStateLoss()

3

Tôi chỉ đơn giản là kiểm tra xem một hoạt động đang bị hủy hoại.

if (!getActivity().isFinishing()) { 
    DialogFragment fragment = MyFragment.newInstance(); 
    fragment.show(getActivity().getSupportFragmentManager(), MyFragment.TAG); 
} 
1

Override show(Fragment manager, String tag) chức năng với phép nhà nước bị mất và thay đổi mDismissed = false;mShownByMe = true; từ chức năng origibal bởi phản ánh:

public class DialogParent extends DialogFragment { 

    @Override 
    public void show(FragmentManager manager, String tag) { 
     try { 
      Field mDismissed = DialogFragment.class.getDeclaredField("mDismissed"); 
      Field mShownByMe = DialogFragment.class.getDeclaredField("mShownByMe"); 
      mDismissed.setAccessible(true); 
      mShownByMe.setAccessible(true); 
      mDismissed.setBoolean(this, false); 
      mShownByMe.setBoolean(this, true); 
     } catch (NoSuchFieldException e) { 
      e.printStackTrace(); 
     } catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
     FragmentTransaction ft = manager.beginTransaction(); 
     ft.add(this, tag); 
     ft.commitAllowingStateLoss(); 
    } 
} 
+0

Bạn cũng có thể bao quanh phương thức hiển thị của cha mẹ với một try-catch, nơi bạn bắt được thêm hộp thoại và sử dụng giao dịch của bạn gọi là 'commitAllowingStateLoss()'. Bằng cách này bạn không cần bất kỳ sự phản ánh nào. – SimonSimCity

0

này thực công trình.

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

Nhưng nhưng vẫn xấu, vì đã nhận lỗi “hoạt động đã bị phá hủy”

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

Vì vậy, giải pháp của tôi là thêm kiểm tra 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(); 
        } 
       } 

trên sa thải:

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

Ngoại lệ này là t hrown bất cứ khi nào một FragmentTrasaction được cam kết sau FragmentManager đã lưu trạng thái của nó.Cách dễ dàng và sạch sẽ là kiểm tra xem FragmentManager đã lưu trạng thái trước khi hiển thị số DialogFragment hay chưa.

if(!getSupportFragmentManager.isStateSaved()) { 
    MyDialogFragment dialogFragment = new MyDialogFragment() 
    dialogFragment.show(getSupportFragmentManager, TAG); 
} 
Các vấn đề liên quan