我可以将接口传递给片段包吗?

时间:2018-05-09 01:43:46

标签: java android android-fragments serialization interface

由于片段需要在配置更改后继续存在,因此Android强烈建议我们在创建片段时应实现自己的newInstance()方法,将必要的数据传递到Bundle而不是{{1} }}

现在,问题是,我想将回调(接口)传递给此片段

首先我尝试创建界面new MyFragment(),然后只使用extends Serializable 但是当Android尝试保存其状态(parcel it)时,抛出异常(Parcelable遇到IOException,编写可序列化对象)。

我知道这样做的正式方法是让调用者Activity实现回调,并在片段的args.putSerializable("myInterface", myInterface)期间引用该活动的回调。
是的,它有效,但感觉很奇怪,因为我实际上是在创建一个库而不是要求用户将回调传递给构建器,我必须告诉他们你的调用者活动必须实现某个接口。
更重要的是,如果我想从另一个onAttach()显示此Fragment该怎么办? Fragment始终附加到onAttach()

那么,是否有一种方法可以让用户将回调传递给片段,并且能够在配置更改(例如设备旋转)后继续存在?

更新

根据要求,这是我要传递的界面:

Activity

我是如何构建这个界面的:

public interface OnImageSelectedListener extends Serializable {
    void onImageSelected (String uri);
}

2 个答案:

答案 0 :(得分:0)

您遇到此问题的原因是,  Glide是非Serializable数据,您无法将其序列化。由于序列化是由Java定义并在JVM上完成的过程,因此它不理解Parcelable,因此失败并出现错误。即使您只是在回调方法中使用它们,这也适用。

但是,由于您正在开发库,因此无法控制Callback接口的使用。因此,解决方案是避免通过序列化来发送此对象。

相反,当您的库的用例开始时(必须有一些入口点来触发用例),您需要请求将您的引用直接传递给您的方法。然后,您可以在必要时维护引用并执行回调。您需要实现一些包装器来实现它。并通过LocalBroadcastReceiver

进行内部沟通

如果无法采用上述方法,那么只有解决方案是要求您的图书馆用户注册LocalBroadcastReceive并通过广播提供结果。

答案 1 :(得分:0)

最后,我得出结论:

我们不应该保留回调。

想象一下回调执行以下代码:
Glide.with(context).load(image).into(imageView);

当设备旋转时,上面的属于一个活动或另一个片段的imageView也会被销毁并重新创建。 保留的回调中引用的旧ImageView不再存在。

这将使Glide抛出异常;或泄漏旧的ImageView,从而泄漏整个Activity

这就是我们应该始终将回调引用到附加Activity的原因 如果调用者是Fragment,而不是引用onAttach()中的回调,只需引用onCreateView()中的父片段:

if (getParentFragment() != null && getParentFragment() instanceof YourInterface) {
    yourCallback = (YourInterface) getParentFragment();
}

所以,如果要回答原来的问题,

  

我可以将接口传递给Fragment的捆绑包吗?

答案是,可能不是,但你不应该。