活动和片段的相互作用

我有一个多个FragmentActivity 。 我想显示一个DialogFragment或者从其中一个Fragment打开另一个Fragment 。 我知道一个Activity应该是一个负责打开Fragment的人,所以我尝试了一些东西。

第一
我试图使用getActivity()并将其getActivity() ,以便我可以在Activity调用一个方法来显示一个Fragment但是这会在Fragment创build一个依赖项,并且我希望尽可能避免添加依赖项。

第二
接下来,我尝试了一个监听器来通知Activity它应该显示一个Fragment 。 所以我在Activity创build了一个类来实现监听器接口。 但我有问题,因为我不得不使用New MyActivity().new Listener(); 当我尝试使用getSupportFragmentManager()时它会抛出Exception ,因为Activity这个实例没有初始化。

第三
然后我试图让Activity实现监听器直接工作,因为那么我只是创build一个依赖与侦听器,而不是活动。 但是现在我已经到了我的Activity将实施2 – 4个不同的界面,这使我犹豫不决,因为它会严重降低凝聚力。

所以我试过的任何方式似乎都跑进了一堵砖墙,并创造了依赖关系,我不确定是否需要创build。 我拧了,必须去与这些选项之一? 如果是的话哪个选项最好? 任何帮助或build议是非常感激。

Solutions Collecting From Web of "活动和片段的相互作用"

就个人而言,我会说片段应该被认为是可重用和模块化的组件。 所以为了提供这种可重用性,片段不应该太了解他们的父母活动。 但是作为回报,活动必须知道他们所持有的碎片。

所以,在我看来,第一个选项不应该被视为您提到的依赖性原因,从而导致高度耦合的代码。

关于第二个选项,片段可以委托任何应用程序stream或UI相关的决定(显示一个新的片段,决定当一个片段特定的事件被触发时要做什么等)。 所以你的听众/callback应该是片段特定的,因此他们应该被分段声明。 持有这些片段的活动应该实现这些接口并决定要做什么。

所以对我来说,第三种select更有意义。 我相信活动在具体callback方面持有和做的更具可读性。 但是,你是对的,你的活动可能成为上帝的对象。

也许你可以检查Square的Otto项目,如果你不想实现几个接口。 这基本上是一个事件公共汽车。

我认为你的第二个select是正确的。

在你的片段中,定义监听器接口:

 class MyFragment ... { public interface IMyFragmentListenerInterface { void DoSomething(); } } 

有活动的实施界面:

 class MyActivity { class MyListener1 implements IMyFragmentListenerInterface { ... } } 

将听众传递给片段。 我喜欢在Fragment的构造函数中完成这个工作,但是只有当你完全由你自己pipe理你的片段时才有效。 你可以添加一个setListener方法到你的片段。

你需要将你的数据从Fragment X传递到你的FragmentActivity,它将把这些数据传递给你的Fragment Y.你通过在你的fragment类中定义的接口来实现这个接口,并实例化onAttach()中定义的callback函数。

有关如何在此处执行此操作的更多信息与其他碎片进行通信

快速的例子,考虑片段A和片段B.片段A是一个列表片段,每当select一个项目时,它将改变片段B中显示的内容。很简单,对吗?

起初,定义片段A是这样的。

  public class FragmentA extends ListFragment{ //onCreateView blah blah blah } 

这里是片段B

 public class FragmentB extends Fragment{ //onCreateView blah blah blah } 

这是我的FragmentActivity,将统治他们两个

 public class MainActivity extends FragmentActivity{ //onCreate //set up your fragments } 

大概你已经有这样的东西了,现在,你将如何改变FragmentA(我们需要从中获取数据的列表片段)。

  public class FragmentA extends ListFragment implements onListItemSelectedListener, onItemClickListener{ OnListItemSelectedListener mListener; //onCreateView blah blah blah // Container Activity must implement this interface public interface OnListItemSelectedListener { public void onListItemSelected(int position); } } @Override public void onAttach(Activity activity) { super.onAttach(activity); // This makes sure that the container activity has implemented // the callback interface. If not, it throws an exception try { mListener = (OnListItemSelectedListener) activity; } catch (ClassCastException e) { throw new ClassCastException(activity.toString() + " must implement OnListItemSelectedListener"); } } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id){ //Here's where you would get the position of the item selected in the list, and pass that position(and whatever other data you need to) up to the activity //by way of the interface you defined in onAttach mListener.onListItemSelected(position); } 

这里最重要的考虑是你的父Activity实现了这个接口,否则你会得到一个exception。 如果成功实施,每次select列表片段中的项目时,您的活动将被通知其位置。 显然,你可以用任何数量或types的参数来改变你的接口,在这个例子中,我们只是传入整数的位置。 希望这个澄清一个人,祝你好运。

创build界面

 public interface ListenFromActivity { void doSomethingInFragment(); } 

Activity类中保留ListenFromActivity接口的ListenFromActivity

  public ListenFromActivity activityListener; 

公开的方法来设置监听器

  public void setActivityListener(ListenFromActivity activityListener) { this.activityListener = activityListener; } 

在activity类中添加一些触发点,这里我使用了用户交互

  @Override public void onUserInteraction() { super.onUserInteraction(); if (null != activityListener) { activityListener.doSomethingInFragment(); } } 

现在在片段类

使你的片段实现接口类

 public class SomeFragment extends Fragment implements ListenFromActivity 

Android工作室会提示你在fragment中实现接口的方法

  void doSomethingInFragment() {//Add your code here } 

在片段onCreate方法中对这样的活动进行最后的部分监听器实例

 ((ListnerActivity) getActivity()).setActivityListener(SomeFragment.this); 

DONE!。 现在您可以从活动中调用片段方法。

你有没有尝试过这样的事情(从片段):

 FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction(); Fragment prev = getActivity().getSupportFragmentManager().findFragmentByTag("some_name"); if (prev != null) { ft.remove(prev); } ft.addToBackStack(null); DialogFragment dialogFragment = DialogFragmentClass.newInstance(); dialogFragment.show(ft, "some_name"); 

让我知道,欢呼。

为了在松耦合中获得最大值,可以使用GreenRobot的Square或EventBus等事件总线。 你的片段可以触发你的活动处理的事件,反之亦然。 这很酷的事情是组件(活动,片段)没有任何关于彼此,你不需要声明任何接口或callback。

我在所有的项目中都使用它,它性能稳定,对性能影响很小(在正常情况下)。