Android Passing Data Between Fragments

Filed Under: Android

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.

Android Passing Data between Fragments

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.

android passing data between fragments

Let’s get started with the implementation of the above flow.

Android Passing Data between Fragments Project Structure

android sharing data between fragments

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="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://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="http://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="http://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.
android passing data between fragments, android sharing object between fragments example

This brings an end to this tutorial. You can download the final Android PassingDataBetweenFragments Project from the link below.

Reference: Fragment Communication

Comments

  1. Joric says:

    Hello, this is the error in my codes java.lang.NullPointerException: Attempt to invoke virtual method ‘void com.example.admin.test2.MainScreen.displayReceivedData(java.lang.String)’ on a null… why would the f be null?

  2. Joric says:

    Hi I did the codes in this website but I have an error which is “Cannot cast ‘com.example.admin.test2.Expense’ to ‘com.example.admin.test2.MainScreen'” I do not know what this means.. I do net have view pager as my fragment transition, I have bottomnav as my fragment transition and I dont know what to do.

  3. Aliton says:

    Thank you very much! Thank you very much! Thank you very!
    I cannot express myself how glad I am because your post!
    I was searching for a solution for more than a week.

    Previously I was declaring ReceiverFragment receiverFragment = new ReceiverFragment(); in MainActivity.
    In the function to send the message to fragmentReceiver I was implementing like this:
    receiverFragment.getMessageFromSender(message);

    That way I was always getting the NullPointerException for the recyclerView in the ReceiverFragment.java.

    With your solution the recyclerView is found and everything is working as expected!
    Thank you very much, once more!

    link for the Stack Overflow:
    https://stackoverflow.com/questions/54464482/android-fragment-to-fragment-communication-update-recyclerview-of-the-receiver

    1. Pankaj says:

      Thanks for the comment and mention it in the SO post too. We are glad that we could help you out.

  4. Mohammad Ali Yazdanpanah says:

    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

    1. Ruchi Shah says:

      Just remove space after “android:switcher:” you get the error because fragment two getting null when you remove space that get the android viewpager resource

      Thanks.

      1. Sagar Koli says:

        Can you please elaborate @RuchiShah , Becuase i am aslo facing this problem. Which space are you talking about? Thanks

      2. ic says:

        Did anyone solve this?

  5. Muhammad Zawawi Bin Manja says:

    how do i send multiple values ?

    1. Anupam says:

      Use Bundle or a Model class and implement Parcelable interface.

  6. Kristopher says:

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

  7. chirag virani says:

    String tag = “android:switcher:” + R.id.viewPager + “:” + 1;
    how use this in tutorial

  8. chirag virani says:

    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

    1. Vishal Rana says:

      Hello Chirag,
      replace this code,
      String tag = “android:switcher:” + R.id.viewPager + “:” + 1;
      by
      String tag = “android:switcher:” + R.id.viewPager + “:” + 3;

      It will work, where 3 is index of 4th tab fragment…

      1. hm shohrab says:

        hello sir … what is “android:switcher:”????
        String tag = “android:switcher:” + R.id.viewPagerId + “:” + 1;
        how it works??? please explained it………please

  9. Shiraz says:

    Thank for nice tutorial. But is there a way to send back the data from fragment two to one again??

    1. Anupam says:

      Create a separate interface for that in fragment two. Same approach.

  10. syafiq says:

    Thank you so much Sifu!

  11. Andrea says:

    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

    1. Anupam says:

      Hi Andrea.
      Either way is good. It depends more so on the data size of the response. In the second method, it’ll take some time to fetch the post response. I’d say go with the first method. You can try out both the methods and see in which the content is loading and displaying faster.

  12. Sauletekis says:

    You’re the boss!! Thank you very much!! Works very well!!

  13. Abhishek says:

    Good tutorial. Was really looking forward fo this

    1. Anupam says:

      Thanks Abhishek. If you want me to cover any topics feel free to comment below!

      1. khushbu says:

        Hi Anupam,
        I follow your tutorials, all r awesome. U keep on adding new topics…. Is there any way so that I can get mails or message or any notification when you add any new tutorial….so that v dont have to search for topics n dates what all u have added new.
        I hope u got my point.

        1. Anupam says:

          Hi Khushbu,
          Specifically for Android, you can always check this link for the latest posts:
          https://www.journaldev.com/author/anupam

        2. Anupam says:

          Hi Khushbu,
          Now with the JournalDev Android App live, you would get an alert whenever any new tutorial is added 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages