最小化时活动崩溃并打开对话框

时间:2016-11-18 11:19:31

标签: android serialization dialog rotation minimize

在我的活动中,显示自定义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");

2 个答案:

答案 0 :(得分:1)

我在你的代码中看到了这一行:

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

如果我猜对了,MyListener由Activity的内部类或Activity本身实现。无论哪种方式,MyListener都拥有对Activity的引用。请注意,如果您要创建一个匿名内部类,那就是:

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

它仍然包含对您的活动的引用。

当片段需要被销毁时,参数Bundle存储在片段状态Parcel中。 Android尝试序列化MyListener,但是Activity不是Serializable,它失败了。

通常的模式是在Fragment中声明你的监听器接口:

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

然后,托管Fragment的Activity实现了这个接口:

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

在你片段的onAttach中,你将Fragment的主机转换为你的回调并设置字段。

@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的{​​{1}}方法版本。上述版本已从API 23弃用。在此之前,Fragments只能由Activities托管。现在,Fragments可以由任意对象托管,并在任何Activity中运行。话虽如此,您可能会在活动中托管您的碎片,并且您的上下文和主机将是相同的。

答案 1 :(得分:0)

尝试使用此方法

dismissAllowingStateLoss();

而不是

dismiss();