如果你想要最干净的面向对象结构,你可以使用多个接口,为回调接口提供与片段相同的嵌套结构,如下所示:
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
}
您付出的代价是,与使用广播接收器或事件总线相比,这会让您编写更多代码。
为什么这是最干净的方法?关注点分离和最少知识原则。该活动仅与外部片段直接交互;内部片段是外部片段的实现细节。
要使内部片段工作,活动必须实现内部回调。这是通过使外部回调扩展内部回调来实现的。
如果您绘制“组件 x 了解组件 y”图表,您会得到:
Activity --> OuterFragment --> InnerFragment
这很干净。这些组件是自包含的和独立的,它们的依赖是显式和(大部分)编译器检查。 InnerFragment 是外部片段的“黑匣子”实现细节,它可以直接在不同的上下文中使用,如果回调不改变(它们可能从一个片段的回调移动到其他情况下)。
如果你不使用回调扩展回调技巧,你会得到这个组件知识图:
Activity --> OuterFragment --> InnerFragment
--------------------> InnerFragment
在这种情况下,内部片段回调依赖对程序员是不可见的。如果您包含片段 X,您希望必须实现 X.Callback,但您还需要 Y.Callback 并不明显。由于这通常由 Fragment 的 onAttach() 方法中的类型转换实现,因此在运行时获取 ClassCastException 之前您不会发现。
顺便说一句,我不喜欢嵌套片段(DialogFragment 很好,但我对嵌套常规片段持怀疑态度)。我认为片段增加了非常多的复杂性,而且我还没有真正遇到过这样的情况,因为移动应用程序的小屏幕尺寸和单一任务焦点是必需的,甚至是可以原谅的。通常最好使用自定义ViewGroup。我建议仅使用片段作为支持手机堆叠布局的一种方式,在平板电脑上使用并排布局,甚至可以使用自定义ViewGroups 以通常更简单但公认不太常见的方式实现。