1

由于 Fragment 需要在配置更改后继续存在,Android 强烈建议我们newInstance()在创建 Fragment 时实现自己的方法,将必要的数据传递给它,Bundle而不是使用new MyFragment().

现在,问题是,我想向这个 Fragment 传递一个回调(接口)

起初我尝试制作我的界面extends Serializable,并简单地使用args.putSerializable("myInterface", myInterface).
但是当 Android 尝试保存它的状态(包裹它)时,会抛出一个异常(Parcelable 遇到 IOException 写入可序列化对象)。

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

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

更新

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

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

以及我如何构建这个接口:

new OnImageSelectedListener() {
        @Override
        public void onSingleImageSelected(String uri) {
            Glide.with(MainActivity.this).load(uri).into(ivImage);
        }
}
4

2 回答 2

0

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

但是由于您正在开发一个库,您将无法控制回调接口的使用。所以解决方案是通过序列化来避免发送这个对象。

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

如果上述方法不可行,那么唯一的解决方案是要求您的图书馆用户注册 LocalBroadcastReceive 并通过广播传递结果。

于 2018-05-09T01:54:57.193 回答
0

最后,我得出结论:

我们不应该保留回调。

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

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

这会使 Glide 抛出异常;或漏旧ImageView而全Activity

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

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

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

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

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

于 2018-05-10T11:46:42.587 回答