简体   繁体   English

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

[英]Activity crashes when minimized and a dialog is opened

On my activity a show a Custom DialogFragement. 在我的活动中,显示一个Custom DialogFragement。 But when I minimize the app while the dialog is opened i get this error 但是当我在打开对话框时最小化应用程序时,会出现此错误

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

For the moment to fix this I have set this in the dialog fragment which seems to works but I don't like these kind of of dirty tricks 为了解决这个问题,我已经在对话框片段中设置了它,似乎可以用,但是我不喜欢这些肮脏的把戏。

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

Anyone can tell me what causes this exception in the first place ? 任何人都可以首先告诉我是什么原因导致此异常?

The onCreate of the custom DialogFragment: 定制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 is an interface. MyListener是一个接口。 I thought at first that this could have been the problem but even if I dont put in the bundle I get the same error, so it must be from something else. 起初我以为这可能是问题所在,但是即使我不放入捆绑包,也会遇到相同的错误,因此一定是其他原因造成的。

Activity side inside a button on click: 在点击按钮旁边的活动侧:

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

I see this line in your code: 我在您的代码中看到此行:

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

If I guess correctly, MyListener is implemented either by an inner class of your Activity or by the Activity itself. 如果我猜对了, MyListener是由Activity的内部类或Activity本身实现的。 Either way, MyListener holds a reference to the Activity. 无论哪种方式,MyListener都会保留对Activity的引用。 Please note that if your are creating an anonymous inner class, that is: 请注意,如果您要创建匿名内部类,则为:

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

it still holds a reference to your Activity. 它仍然包含对您的活动的引用。

When the Fragment needs to be destroyed, the arguments Bundle is stored in the fragment state Parcel. 当需要销毁片段时,参数Bundle将存储在片段状态Parcel中。 Android tries to serialize MyListener, however Activity is not Serializable and it fails. Android尝试对MyListener进行序列化,但是“活动”不可序列化且失败。

The usual pattern is to declare your listener interface in your Fragment: 通常的模式是在Fragment中声明您的侦听器接口:

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

Then an Activity that hosts the Fragment implements this interface: 然后,承载Fragment的Activity会实现此接口:

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

In onAttach of your Fragment you cast the Fragment's host to your Callbacks and set the field. 在Fragment的onAttach ,将Fragment的主机转换为Callbacks并设置字段。

@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 In the documentation you may see a version of onAttach method taking an Activity . PS在文档中,您可能会看到采用ActivityonAttach方法版本。 The version above is deprecated from API 23. Until then, Fragments could be hosted only by Activities. API 23不推荐使用上述版本。在此之前,片段只能由活动托管。 Now, Fragments can be hosted by arbitrary objects and operate in any Context . 现在,片段可以由任意对象托管,并可以在任何Context That being said, you probably will host your Fragments inside Activities anyway, and your context and host will be the same. 话虽如此,您可能仍将在“活动”中托管您的“片段”,并且您的上下文和主机将相同。

try using this method 尝试使用这种方法

dismissAllowingStateLoss();

instead of 代替

dismiss();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM