一个或多个接口?

One or multiple interfaces?

我有一个 Activity A,其中包含一个 Fragment B,另一个 Fragment C 包含一个 ListView,其中包含一些列表项。

列表项如何与 Activity 通信?一定要一层层通过Activity引用,直到到达列表项吗?我是否必须创建 多个 接口并让通信逐级返回 Activity

更新:

看完@Barend的回答后,这是我的代码:Fragment C有一个接口CFragment B 有一个扩展 C 的接口 BActivity A实现了B,也就是说它也实现了C中的方法。在 Fragment C 中,我有一个 mListener 字段,它在 onAttach(Context) 生命周期回调中分配给 getActivity()

如果您需要与来自 fragmentActivity 通信,您可以通过使用 getActivity() 从任何嵌套的 Fragment 获取您的 Activity。 如果您需要从 Activity 访问 Fragment,请使用 FragmentManager:

FragmentManager manager = getFragmentManager();
Fragment f = manager.findFragmentByTag("Your fragment tag");

如果您想要最干净的面向对象结构,您可以使用多个接口,为回调接口提供与片段相同的嵌套结构,如下所示:

public class InnerFragment extends Fragment {

    public interface Callback {
        // Defines all callback methods required by inner fragment
    }
}

public class OuterFragment extends Fragment {

    public interface Callback
            extends InnerFragment.Callback {
        // Defines all callback methods required by outer fragment
        // Inherits all callback methods required by inner fragment
    }
}

public class HostActivity extends Activity
        implements OuterFragment.Callback {

    // implements the callback methods of both fragments, but
    // references only the outer fragment
}

你付出的代价是,与使用广播接收器或事件总线相比,这会让你编写更多的代码。

为什么这是最干净的方法?关注点分离和最少知识原则。 activity 仅与外部片段直接交互;内部片段是外部片段的实现细节。

要使内部片段正常工作,activity 必须实施内部回调。这是通过使外部回调扩展内部回调来实现的。

如果绘制 "component x has knowledge of component y" 图表,您会得到:

Activity --> OuterFragment --> InnerFragment

这很干净。这些组件是 self-containedindependent 并且它们的依赖关系是 explicit 和(大部分) 编译器检查。 InnerFragment 是外部片段的 "black box" 实现细节,它可以直接在不同的上下文中使用,并且如果回调不改变(它们可能从在某些情况下,一个片段对另一个片段的回调)。

然而,如果您不使用回调扩展回调技巧,您将获得此组件知识图:

Activity --> OuterFragment --> InnerFragment
         --------------------> InnerFragment

在这种情况下,内部片段回调依赖对程序员是不可见的。如果您要包含片段 X,您预计必须实施 X.Callback,但显然您还需要 Y.Callback。由于这通常是通过在 Fragment 的 onAttach() 方法中进行类型转换来实现的,因此在 运行 时间获得 ClassCastException 之前,您不会发现。


顺便说一句,我不喜欢嵌套片段(DialogFragment 很好,但我对嵌套常规片段持怀疑态度)。我认为片段增加了很多复杂性,而且我还没有真正遇到过需要甚至可以原谅移动应用程序的小屏幕尺寸和单一任务焦点的情况。您通常最好使用自定义 ViewGroup。我建议仅将片段用作支持在平板电脑上使用并排布局的手机上的堆叠布局的一种方式,甚至可以使用自定义 ViewGroups 以一种通常更简单但公认不太常见的方式实现。