两个片段之间的通信 - 这是正确的方法吗?

时间:2015-01-04 11:56:43

标签: android android-fragments

我已阅读this手册,也阅读了this本书。 developer.android.com说我应该通过活动实现沟通。但是这本书说我可以使用setTargetFragment()并手动调用onActivityResult()来获取其他片段的目标片段。每种方法都有效,但哪种方法正确?什么是setTargetFrament(),如果我不能用它来与其他片段进行通信?

1 个答案:

答案 0 :(得分:2)

setTargetFrament()和getTargetFrament()可以在一个启动另一个片段的片段的上下文中使用。第一个片段可以将其自身作为对第二个片段的引用:

MyFragment newFrag = new MyFragment();
newFrag.setTargetFragment(this, 0);
getFragmentManager().beginTransaction().replace(R.id.frag_one, newFrag).commit();

现在newFrag可以使用getTargetFrament()直接从oldFrag检索oldFrag和访问方法。

然而,这并不是建议在通常情况下使用的东西。

片段之间的通信推荐方式是通过父活动来完成的,如docs所述:

Often you will want one Fragment to communicate with another, 
for example to change the content based on a user event. 
All Fragment-to-Fragment communication is done through the associated Activity. 
Two Fragments should never communicate directly.

以下是一个例子:

主要活动的布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <FrameLayout 
        android:id="@+id/frag_one"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
    <FrameLayout 
        android:id="@+id/frag_two"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>
</LinearLayout>

活动:

public class MainActivity extends Activity
{
    private MyFragment f1;
    private MyFragment f2;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Bundle b1 = new Bundle();
        b1.putString("name", "Fragment One");
        f1 = MyFragment.createNew(b1);//we create a new fragment instance
        f1.setOnReceiveListener(new MyFragment.ReceiveListener()//we create a new ReceiveListener and pass it to the fragment
        {
            @Override
            public void recv(String str)
            {
                //f1 has sent data to the activity, the activity passes forward to f2 
                f2.send(str);
            }
        });
        //we attach the fragment to the activity
        getFragmentManager().beginTransaction().add(R.id.frag_one, f1, "frag_one").commit();


        //we repeat the above process for the second fragment
        Bundle b2 = new Bundle();
        b2.putString("name", "Fragment Two");
        f2 = MyFragment.createNew(b2);
        f2.setOnReceiveListener(new MyFragment.ReceiveListener()
        {
            @Override
            public void recv(String str)
            {
                f1.send(str);
            }
        });
        getFragmentManager().beginTransaction().add(R.id.frag_two, f2, "frag_two").commit();        
    }
}

片段布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <Button 
        android:id="@+id/frag_btn"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:layout_alignParentTop="true"/>
    <TextView
        android:id="@+id/frag_txt"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:layout_below="@+id/frag_btn"
        android:textSize="10sp"/>
</RelativeLayout>

片段类:

public class MyFragment extends Fragment
{
    private ReceiveListener recv_list;
    private Button btn;
    private TextView txt;

    //static factory function that creates new fragments  
    public static MyFragment createNew(Bundle b) 
    {
        MyFragment f = new MyFragment();
        f.setArguments(b);
        return f;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        return inflater.inflate(R.layout.fragment, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState)
    {
        super.onViewCreated(view, savedInstanceState);

        btn = (Button) view.findViewById(R.id.frag_btn);
        txt = (TextView) view.findViewById(R.id.frag_txt);

        //we retrieve the passed arguments (in this case the name)
        Bundle b = getArguments();
        final String name = b.getString("name");

        btn.setText(name);
        btn.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                if(null != recv_list)
                {
                    //now we pass the data to the parent activity
                    recv_list.recv(name + " says hello!");
                }
            }
        });
    }

    //the activity passes data to the fragment using this method
    public void send(String s)
    {
        txt.append(s + "\n");
    }

    //helper method that will set the listener
    public void setOnReceiveListener(ReceiveListener l)
    {
        recv_list = l;
    }

    //the declaration of the listener
    public interface ReceiveListener
    {
        public void recv(String str);
    }
}