
In this tutorial, we’ll be developing an application that contains TabLayout, ViewPager and Fragments. We’ll implement a functionality that passes data from one Fragment to the other fragment.
Intents are only usable for sending data on an Activity level. To pass data between fragments we need to create our own interfaces. The flow to send a String data from one Fragment to another is shown below. 
 Let’s get started with the implementation of the above flow.
 The xml layout for the MainActivity.java class is given below.
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.journaldev.passingdatabetweenfragments.MainActivity">
    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />
        <android.support.design.widget.TabLayout
            android:id="@+id/tabs"
            style="@style/MyStyle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabGravity="fill"
            app:tabMode="fixed" />
    </android.support.design.widget.AppBarLayout>
    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
The styles for the TabLayout and ToolBar are defined in the styles.xml file as shown below.
<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>
    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
    <style name="MyStyle" parent="Widget.Design.TabLayout">
        <item name="tabIndicatorColor">#FFFF</item>
        <item name="tabIndicatorHeight">5dp</item>
        <item name="tabPaddingStart">8dp</item>
        <item name="tabPaddingEnd">8dp</item>
    </style>
</resources>
The ViewPagerAdapter.java is where the Fragments are initialised. The code is given below.
public class ViewPagerAdapter extends FragmentPagerAdapter {
    public ViewPagerAdapter(FragmentManager fm) {
        super(fm);
    }
    @Override
    public Fragment getItem(int position) {
        Fragment fragment = null;
        if (position == 0) {
            fragment = new FragmentOne();
        } else if (position == 1) {
            fragment = new FragmentTwo();
        }
        return fragment;
    }
    @Override
    public int getCount() {
        return 2;
    }
    @Override
    public CharSequence getPageTitle(int position) {
        String title = null;
        if (position == 0) {
            title = "Tab-1";
        } else if (position == 1) {
            title = "Tab-2";
        }
        return title;
    }
}
FragmentOne would be sending the data entered in EditText to FragmentTwo. The xml layout for fragment_one.xml is given below.
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fillViewport="true">
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <EditText
            android:id="@+id/inMessage"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_above="@+id/btnPassData"
            android:layout_margin="16dp"
            android:hint="Enter here" />
        <Button
            android:id="@+id/btnPassData"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="PASS DATA TO FRAGMENT TWO" />
    </RelativeLayout>
</ScrollView>
The xml layout for fragment_two.xml is given below.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/txtData"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:layout_centerInParent="true"
        android:text="No data received" />
</RelativeLayout>
The code for FragmentOne.java class is given below.
package com.journaldev.passingdatabetweenfragments;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
public class FragmentOne extends Fragment {
    SendMessage SM;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(
                R.layout.fragment_one, container, false);
        return rootView;
    }
    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Button btnPassData = (Button) view.findViewById(R.id.btnPassData);
        final EditText inData = (EditText) view.findViewById(R.id.inMessage);
        btnPassData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SM.sendData(inData.getText().toString().trim());
            }
        });
    }
    interface SendMessage {
        void sendData(String message);
    }
    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            SM = (SendMessage) getActivity();
        } catch (ClassCastException e) {
            throw new ClassCastException("Error in retrieving data. Please try again");
        }
    }
}
The Custom Interface namely SendMessage is initialised in the onAttach method above. This interface would be implemented in the MainActivity.java that we’ll be seeing shortly. The code for FragmentTwo.java class is given below.
package com.journaldev.passingdatabetweenfragments;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class FragmentTwo extends Fragment {
    TextView txtData;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(
                R.layout.fragment_two, container, false);
        return rootView;
    }
    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        txtData = (TextView)view.findViewById(R.id.txtData);
    }
    protected void displayReceivedData(String message)
    {
        txtData.setText("Data received: "+message);
    }
}
The displayReceivedData() would be called on the instance of FragmentTwo.java from inside the Custom Interface’s method inside the MainActivity.java as shown below.
package com.journaldev.passingdatabetweenfragments;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.Toolbar;
public class MainActivity extends AppCompatActivity implements FragmentOne.SendMessage{
    TabLayout tabLayout;
    ViewPager viewPager;
    ViewPagerAdapter viewPagerAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        viewPager = (ViewPager) findViewById(R.id.viewPager);
        viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(viewPagerAdapter);
        tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
    }
    @Override
    public void sendData(String message) {
        String tag = "android:switcher:" + R.id.viewPager + ":" + 1;
        FragmentTwo f = (FragmentTwo) getSupportFragmentManager().findFragmentByTag(tag);
        f.displayReceivedData(message);
    }
}
The sendData() method in the above code gets triggered as soon as the Button in FragmentOne is pressed. We fetch the FragmentTwo that was already initialised in ViewPagerAdapter using the method findFragmentByTag. The output of the above application in action is given below. 
 This brings an end to this tutorial. You can download the final Android PassingDataBetweenFragments Project from the link below.
Download Android Passing Data Between Fragments Example Project
Reference: Fragment Communication
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Hi Anupam, thanks for the tutorial, very helpful. I’m trying to simulate a blog app using a json file, the main screen show a list of posts, and when I click on it, it opens the post, my question is, should I send all data from the first fragment to the second (title, image, text) or should I do like websites where we send the post ID and when the new page is opened we fetch all the content by the ID. Regards, Andrea
- Andrea
Thank for nice tutorial. But is there a way to send back the data from fragment two to one again??
- Shiraz
Hello anupam chugh this is nice tutorial.but i have some help. In this tutorial 2 tab but i am using 4 tab and i have pass value first fragment to fourth fragment but error in tag value how to solve this error
- chirag virani
String tag = “android:switcher:” + R.id.viewPager + “:” + 1; how use this in tutorial
- chirag virani
I also thank you so much! When you create a new project with Tabbed Activity my PagerAdapter class extends to FragmentStatePagerAdapter insted of FragmentPagerAdapter. error: Attempt to invoke virtual method on a null object reference public class PagerAdapter extends FragmentPagerAdapter { }
- Kristopher
Hi! My code is like your code without any difference. Of course i don’t declare AppBarLayout and Toolbar, just i declare TabLayout and ViewPager. But when i click on Button in Fragment_One, my app stopped and in LogCat i get Null Pointer Exception in lines: MainActivity.sendData - f.displayReceivedData(message); and FragmentOne.onClick: - SM.sendData(inData.getText().toString().trim()); Error is: java.lang.NullPointerException: Attempt to invoke virtual method ‘void com.my.testtablayout.FragmentTwo.displayReceivedData(java.lang.String)’ on a null object reference Why? Thankyou for your answer
- Mohammad Ali Yazdanpanah
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.