How to Send Data Between Two Fragments in Android
Fragments are reusable UI components commonly used in modern Android applications.
Many Android applications require communication between fragments for:
- Form updates
- Search filters
- Chat interfaces
- Dashboard synchronization
- Master-detail layouts
Since fragments should remain modular and reusable, direct fragment-to-fragment communication is not recommended.
Instead, communication usually happens through:
- Activity interfaces
- Shared ViewModel
- Fragment Result API
In this tutorial, we will learn how to send data between two fragments using interfaces and the hosting Activity.
What We Will Build
In this Android example:
- Fragment A sends text to Fragment B
- Fragment B sends text to Fragment A
- Activity acts as communication bridge
- Fragments remain reusable and modular
How Fragment Communication Works
The workflow is:
- User enters text in Fragment A
- Fragment A sends data to Activity using interface
- Activity forwards data to Fragment B
- Fragment B updates UI
The same process works in reverse direction.
Step 1 — Create activity_main.xml
Create the main Activity layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/containerA"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<FrameLayout
android:id="@+id/containerB"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
Step 2 — Create MainActivity.java
package com.example.fragmentcommunication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity
extends AppCompatActivity
implements FragmentA.FragmentAListener,
FragmentB.FragmentBListener {
private FragmentA fragmentA;
private FragmentB fragmentB;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentA = new FragmentA();
fragmentB = new FragmentB();
getSupportFragmentManager()
.beginTransaction()
.replace(
R.id.containerA,
fragmentA
)
.replace(
R.id.containerB,
fragmentB
)
.commit();
}
@Override
public void onInputASent(CharSequence input) {
fragmentB.updateEditText(input);
}
@Override
public void onInputBSent(CharSequence input) {
fragmentA.updateEditText(input);
}
}
Step 3 — Create FragmentA.java
package com.example.fragmentcommunication;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
public class FragmentA extends Fragment {
private FragmentAListener listener;
private EditText editText;
public interface FragmentAListener {
void onInputASent(CharSequence input);
}
@Nullable
@Override
public View onCreateView(
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState
) {
View view = inflater.inflate(
R.layout.fragment_a,
container,
false
);
editText =
view.findViewById(R.id.editText);
Button button =
view.findViewById(R.id.buttonOk);
button.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onInputASent(
editText.getText()
);
}
});
return view;
}
public void updateEditText(
CharSequence newText
) {
editText.setText(newText);
}
@Override
public void onAttach(
@NonNull Context context
) {
super.onAttach(context);
if (context instanceof FragmentAListener) {
listener =
(FragmentAListener) context;
} else {
throw new RuntimeException(
context.toString()
+ " must implement FragmentAListener"
);
}
}
}
Step 4 — Create FragmentB.java
package com.example.fragmentcommunication;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
public class FragmentB extends Fragment {
private FragmentBListener listener;
private EditText editText;
public interface FragmentBListener {
void onInputBSent(CharSequence input);
}
@Nullable
@Override
public View onCreateView(
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState
) {
View view = inflater.inflate(
R.layout.fragment_b,
container,
false
);
editText =
view.findViewById(R.id.editText);
Button button =
view.findViewById(R.id.buttonOk);
button.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onInputBSent(
editText.getText()
);
}
});
return view;
}
public void updateEditText(
CharSequence newText
) {
editText.setText(newText);
}
@Override
public void onAttach(
@NonNull Context context
) {
super.onAttach(context);
if (context instanceof FragmentBListener) {
listener =
(FragmentBListener) context;
} else {
throw new RuntimeException(
context.toString()
+ " must implement FragmentBListener"
);
}
}
}
Step 5 — Create fragment_a.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp"
android:background="#A5D6A7">
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/buttonOk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send"/>
</LinearLayout>
Step 6 — Create fragment_b.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp"
android:background="#90CAF9">
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/buttonOk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Send"/>
</LinearLayout>
Why Interfaces Are Used
Interfaces help:
- Reduce tight coupling
- Improve modularity
- Make fragments reusable
- Separate responsibilities cleanly
Common Mistakes Developers Make
1. Direct Fragment References
Direct fragment communication creates tightly coupled code.
2. Forgetting Interface Implementation
Activity must implement fragment listener interfaces.
3. Updating Views Before Initialization
Always ensure fragment views are initialized before updating UI.
Modern Android Alternatives
Modern Android development usually prefers:
- Shared ViewModel
- LiveData
- StateFlow
- Fragment Result API
- Jetpack Compose state management
Shared ViewModel vs Interface Communication
| Interface Communication | Shared ViewModel |
|---|---|
| Good for simple communication | Better for scalable apps |
| Activity acts as bridge | Lifecycle-aware state sharing |
| More manual implementation | Cleaner architecture |
FAQ
Can fragments communicate directly?
Technically yes, but it is not recommended because it increases coupling.
What is the modern recommended approach?
Shared ViewModel with LiveData or StateFlow is the modern recommended solution.
Why use fragments instead of multiple activities?
Fragments provide better UI flexibility and reusable modular components.
Conclusion
Fragment communication is an important part of Android application architecture.
Using interfaces allows fragments to remain modular while communicating safely through the hosting Activity.
Modern Android applications should combine fragment communication with lifecycle-aware architecture patterns such as Shared ViewModel and StateFlow.
About the Author
Salil Jha is a Full Stack and Mobile Developer specializing in Android, React Native, fintech systems, scalable SaaS platforms, and developer tooling products.
CodeChain Dev — Build Modern Products. Solve Real Problems.
Deep Structural Diagnostics.
Mastering JSON is only the first step. Use our industrial-grade workbench to format, validate, and synthesize models for your production APIs.