2013-07-03 147 views
9

我有一个Activity与多个Fragment s。我想显示或从Fragment之一开放另一个Fragment。我知道一个Activity应该是开放Fragment s的任务,所以我尝试了几件事情。活动和片段互动

FIRST
我试图用getActivity()并投它,所以我可以调用Activity的方法来显示Fragment然而,这会在Fragment依赖与Activity,我想避免添加依赖如果可能的话。

第二
接下来,我尝试了听众通知Activity它应该表现出Fragment。所以我在Activity中创建了一个类来实现监听器接口。但是我遇到了问题,因为我不得不使用New MyActivity().new Listener();,并且当我尝试使用getSupportFragmentManager()时它会抛出Exception,因为Activity的这个实例未初始化。

第三
我又试图有Activity直接实现监听器的工作原理,因为那时我只创建与听众,而不是活动的依赖性。但是现在我已经到了我的Activity将实施2 - 4个不同的界面,这使我犹豫不决,因为它会严重降低凝聚力。

因此,我试过的任何方式似乎都跑进了一堵砖墙,并创建依赖关系,我不知道我需要创建。我是否搞砸了,不得不采取其中一种选择?如果是的话哪个选项最好?任何帮助或建议是非常感谢。

+0

有很多方法可以做到这一点,我喜欢尽可能的去耦合,为此我喜欢一个事件总线。请参阅otto,例如:http://square.github.io/otto/。 (让你摆脱所有的界面/监听器,传递数据,用强大的类型来做,用简洁明了的方式来做。) –

+0

它看起来很有希望。我必须检查一下。谢谢你的提示。 –

回答

10

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

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

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

因此,对我来说,第三种选择更有意义。我相信活动在具体回调方面持有和执行的内容更具可读性。但是,你是对的,你的活动可能会成为上帝的对象。

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

+0

感谢您和@Charlie Collins将我指向Otto图书馆。这看起来非常有希望,似乎它会完成我期待的。感谢大家的帮助。 –

3

我认为你的第二个选择是在正确的轨道上。

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

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

有活动实现的接口:

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

传递到听者的片段。我喜欢在Fragment的构造函数中完成它,但只有当你完全由你自己管理片段时才有效。相反,您可以将setListener方法添加到片段中。

+3

“setListener”方法存在问题:如果操作系统销毁并重新创建了片段(使用默认的空白构造函数),则对该侦听器的引用将丢失。实现这一目标的最好方法是将代码放入'onAttach'方法中,将片段的父活动连接为侦听器,并在运行时检查它是否支持所需的接口。请参阅http://developer.android.com/guide/components/fragments.html:'创建活动回调到活动'。 –

0

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

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"); 

让我知道,欢呼声。

2

您需要将您的数据从Fragment X传递到您的FragmentActivity,这会将此数据传递到您的Fragment Y.您通过在您的fragment类中定义的接口来实现此目的,并实例化一个在onAttach()。如何做到这一点这里 Communication With other Fragments

简单的例子

更多信息,可以考虑片段A和片段B片段A是列表片段,每当一个项目被选中它会有什么变化显示在片段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实现了这个接口,否则你会得到一个异常。如果成功实施,每次选择列表片段中的项目时,您的活动都会被通知其位置。很明显,你可以用任何数量或类型的参数来改变你的接口,在这个例子中,我们只是传入整数位置。希望这个澄清一个人,祝你好运。

0

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

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

2

创建界面

public interface ListenFromActivity { 
    void doSomethingInFragment(); 
} 

Activity类保持ListenFromActivity接口refrence

public ListenFromActivity activityListener; 

张扬方法来设置监听

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

添加一些触发点在活动课, H趁着我已经使用的用户交互

@Override 
    public void onUserInteraction() { 
     super.onUserInteraction(); 

     if (null != activityListener) { 
      activityListener.doSomethingInFragment(); 
     } 
    } 

现在片段类

让你的片段实现接口类

public class SomeFragment extends Fragment implements ListenFromActivity 

的Android工作室将提示您实现接口的方法在片段

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

最后部部分听者实例类似这样的活性片段onCreate方法

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

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