Srikanth Technologies

Inter-Fragment Communication

In this blog I will show how to handle the following tasks related to Fragments.

In the above Activity, when we click on Show Date and Time button, FragmentA invokes a method in Activity, which in turn calls a method in FragmentB to display date and time.

The primary task is to have communication between two Fragments hosted in the same Activity.

Let’s first create an Interface that is to be implemented by an Activity so that a Fragment hosted in that Activity can communicate with Activity through methods of that interface.

DateListener interface contains only one method called showDate(), which is implemented by Activity and called by Fragment in the Activity.

DateListener.java

package com.srikanthpragada.demo;

public interface DateListener {
     void showDate();
}
Remember, we need to make Activity and Fragment as loosely coupled as possible. That means the name of the Activity and Fragment are not known to each other, yet they can communicate with each other through DateListener interface.

Now lets create an Activity that implements DateListener interface and also hosts two Fragments – FragmentA and FragmentB.

Activity uses FragmentManager to get access to a Fragment hosted in it. We use id of the Fragment and do not assume anything about name of the Fragment there by making the communication between Activity and Fragment loosely coupled.

Here is the code for FragmentsActivity and its layout.

FragmentsActivity.java

package com.srikanthpragada.demo;

import android.app.Activity;
import android.app.FragmentManager; 
import android.os.Bundle;
import android.util.Log;

public class FragmentsActivity extends Activity implements  DateListener {

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

    // This method is called from a Fragment so that it can communicate 
    // with another Fragment hosted in the same Activity
    public void showDate() {
        FragmentManager fm = getFragmentManager();  //  Get FragmentManager to get access to 
        DateListener fragment = (DateListener) fm.findFragmentById(R.id.fragmentb);
        frgment.showDate();
    }
}

activity_fragments.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.srikanthpragada.demo.FragCommActivity">

    <fragment
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:name="com.srikanthpragada.demo.FragmentA"
        android:id="@+id/fragmenta"
        android:layout_weight="1"
        />

    <fragment
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:name="com.srikanthpragada.demo.FragmentB"
        android:id="@+id/fragmentb"
        />
</LinearLayout>
    

FragmentA

FragmentA contains a button. When clicked it invokes showDate() method of hosting Activity so that Activity invokes showDate() method of another Fragment – FragmentB , hosted in the same Activity.

Here is the code for FragmentA, which has a button that invokes showDate() method of the hosting Activity when it is clicked.

It gets a reference to Activity in which it is hosted through attach() callback method.

FragmentA.java

package com.srikanthpragada.demo;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

public class FragmentA extends Fragment {
    private DateListener dateListener;
    private Button btnShow;
   
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v =  inflater.inflate(R.layout.fragment_a, container, false);
        btnShow = (Button) v.findViewById(R.id.btnShowDate);
        // associate  OnClickListener with button . It must be done through code and not through XML
        btnShow.setOnClickListener(
            new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                if (dateListener != null) {
                    dateListener.showDate();
                }
              }
           }
        );
        return v;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        
        // if hosting Activity doesn't implement DateListener interface then throw error 
        if (activity instanceof DateListener) {
            dateListener = (DateListener) activity;
        } else {
            throw new RuntimeException(activity.toString()
                    + " must implement DateListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        dateListener = null;
    }
}

fragment_a.xml

Here is layout for FragmentA. It contains a button.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.srikanthpragada.demo.FragmentA">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show Date and Time"
        android:id="@+id/btnShowDate"
        android:layout_gravity="center" />

</FrameLayout>

FragmentB

FragmentB is second fragment hosted in the Activity. It implements DateListener and showDate() method.

When a button in FragmentA is clicked, it calls showDate() method of Activity and then Acvitity calls showDate() method of this Fragment.

FragmentB.java

package com.srikanthpragada.demo;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.Date;

public class FragmentB extends Fragment  implements DateListener{
    TextView tvDate;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,  Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_b, container, false);
        tvDate = (TextView) view.findViewById(R.id.textDate);
        return view;
    }
    public void showDate()
    {
        tvDate.setText( new Date().toString());
    }
}

fragment_b.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#FFFF00"
    tools:context="com.srikanthpragada.demo.FragmentB">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textDate"
        android:layout_gravity="center"
        android:textSize="30sp"
        android:text="" />
</FrameLayout>