0

I have read this manual and also i'm reading this book. developer.android.com says i should implement communication through activity. But the book says i can use setTargetFragment() and call onActivityResult() by hand for target fragment from other fragment. Each approach works but which is right? What is setTargetFrament() for, if i can't use it for communication with other fragment?

Kastaneda
  • 739
  • 1
  • 8
  • 15

1 Answers1

2

setTargetFrament() and getTargetFrament() can be used in the context of one fragment that starts another fragment. The first fragment can pass its self as a reference to the second fragment:

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

Now newFrag can use getTargetFrament() to retrieve the oldFrag and access methods from oldFrag directly.

This is not however something that is recommanded to be used on an usual basis.

The recommanded way of communication between fragments is to be done through the parent activity, as the docs mention:

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.

Here is a example of that:

the layout for the main activity:

<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>

the Activity:

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();        
    }
}

The fragment layout:

<?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>

The fragment class:

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);
    }
}
Goran Horia Mihail
  • 3,536
  • 2
  • 29
  • 40