2016-11-18 71 views
0

在我的活動中,顯示一個Custom DialogFragement。但是,當我最小化的應用程序,而對話框打開我得到這個錯誤當最小化並打開對話框時,活動崩潰

java.lang.RuntimeException: Parcelable encountered IOException writing serializable object (name = xxx.xxx.MyActivity$24) 
at android.os.Parcel.writeSerializable(Parcel.java:1468) 
at android.os.Parcel.writeValue(Parcel.java:1416) 
at android.os.Parcel.writeArrayMapInternal(Parcel.java:686) 
at android.os.BaseBundle.writeToParcelInner(BaseBundle.java:1330) 
at android.os.Bundle.writeToParcel(Bundle.java:1079) 
at android.os.Parcel.writeBundle(Parcel.java:711) 
at android.support.v4.app.FragmentState.writeToParcel(Fragment.java:144) 
at android.os.Parcel.writeTypedArray(Parcel.java:1254) 
at .... 
... 23 more 
java.io.NotSerializableException: xxx.xxx.MyActivity 
at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1344) 
xxxxx 

眼下解決這個問題我已經在這似乎作品的對話片段設置這一點,但我不喜歡這幾樣的骯髒的技巧

@Override 
    public void onPause() { 
    dismiss(); 
    super.onPause(); 
    } 

任何人都可以告訴我是什麼原因導致此異常?

定製DialogFragment的OnCreate:

public static MyCustomDialog newInstance(double lat, double lng, MyListener listener) { 
    MyCustomDialog dialogFragment = new MyCustomDialog(); 
    Bundle bundle = new Bundle(); 
    bundle.putDouble(ARG_LAT, lat); 
    bundle.putDouble(ARG_LNG, lng); 
    bundle.putSerializable(ARG_LISTENER, listener); 
    dialogFragment.setArguments(bundle); 
    return dialogFragment; 
    } 

@Nullable 
    @Override 
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 
    View view = inflater.inflate(R.layout.dialog_layout, null, false); 
    final double lat = getArguments().getDouble(ARG_LAT); 
    final double lng = getArguments().getDouble(ARG_LNG); 
    listener = (MyListener) getArguments().getSerializable(ARG_LISTENER); 
    TextView saveBtn = (TextView) view.findViewById(R.id.save_btn); 
    saveBtn.setOnClickListener(new View.OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      /* some processing */ 
      listener.onSave(); 
      } 
    }); 
return view; 
} 

myListener的是一個接口。我一開始以爲這可能是問題所在,但即使我沒有放入包中,我也會得到同樣的錯誤,所以它必須來自其他方面。一個按鈕內

活動側點擊:

MyCustomDialog myCustomDialog = MmyCustomDialog.newInstance(lat, lon, listener); 
myCustomDialog.show(getSupportFragmentManager(), "tag"); 
+0

它看起來像試圖保存包中的某些內容以便稍後重新啓動活動。如果在對話框打開的情況下更改方向,它是否也會崩潰? – Nemesis

+0

是的,它也崩潰 – Johny19

回答

0

嘗試使用這種方法

dismissAllowingStateLoss(); 

代替

dismiss(); 
1

我看到這行代碼:

listener = (MyListener) getArguments().getSerializable(ARG_LISTENER); 

如果我猜對了,MyListener是由您的Activity的內部類或活動本身實現的。無論哪種方式,MyListener都會保存對Activity的引用。請注意,如果你正在創建一個匿名內部類,那就是:

MyListener listener = new MyListener() { ... } 

它仍然持有對您的活動的引用。

當片段需要被銷燬時,參數Bundle被存儲在片段狀態Parcel中。 Android嘗試序列化MyListener,但Activity不是可序列化的,並且失敗。

通常的模式是聲明監聽器接口您的片段:

public class MyFragment extends Fragment { 
    ... 
    public interface Callbacks { 
     void doSomething(); 
    } 
    ... 

然後承載碎片的活動實現了這個接口:

public class MyActivity extends AppCompatActivity implements MyFragment.Callbacks { 
    ... 
    @Override 
    public void doSomething() { 
     // do your stuff 
    } 
    ... 

在你片段的onAttach你投的片段的主機到您的回調並設置字段。

@Override 
public void onAttach(Context context) { 
    super.onAttach(context); 

    if (getHost() instanceof Callbacks) { 
     mCallbacks = (Callbacks) getHost(); 
    } else { 
     throw new AssertionError("Host does not implement Callbacks!"); 
    } 
} 

PS在文檔中,你可能會看到onAttach方法的版本服用Activity。上述版本已從API 23棄用。在此之前,Fragments只能由活動託管。現在,碎片可以由任意對象託管並在任何Context中運行。話雖如此,你可能會將你的碎片存放在活動中,而你的上下文和主機將是相同的。

+0

「如果我猜對了,MyListener是你的活動的內部類」 不,它不是。它是一個新文件中的單獨界面。起初它是在我認爲是問題的MyCustomDialog中。但問題仍然存在後,我把它移動到一個新的文件 我寫過的問題,即使沒有MyListener它崩潰以及 – Johny19

+1

對不起,錯誤的措辭。我的意思是你的Activity的內部類實現你的接口,或者你的Activity實現你的接口。我更新了答案以澄清這一點。 –

+0

但是你在哪裏看到我正在使用片段?我在這裏談論一個DialogFragment。 – Johny19