Passing data between Activities and Fragments is one of the most common tasks in Android development.
However, many beginners incorrectly pass values using custom Fragment constructors, which can cause runtime issues and lifecycle problems.
Modern Android development recommends using:
- Bundle arguments
- Factory methods
- setArguments()
In this tutorial, we will learn:
- Why overloaded Fragment constructors are dangerous
- How to pass values using Bundle
- How to create a factory method
- Modern Android Fragment best practices
Why Custom Fragment Constructors Are Not Recommended
Android recreates Fragments automatically during:
- Screen rotation
- Configuration changes
- Process recreation
- Low memory recovery
During recreation, Android uses the default no-argument constructor.
If developers create custom constructors like:
public ExampleFragment(String text) {
}
Android may throw:
InstantiationException
or lifecycle restoration problems.
Correct Way to Pass Data to Fragments
Modern Android recommends:
- Create a Bundle
- Add values into Bundle
- Call setArguments()
- Retrieve values using getArguments()
What Is a Factory Method?
A Factory Method is a static method used to safely create Fragment instances with arguments.
Benefits:
- Cleaner code
- Better lifecycle handling
- Avoids constructor issues
- Improves reusability
What We Will Build
In this Android example:
- MainActivity creates a Fragment
- Bundle values are passed safely
- Fragment retrieves arguments
- UI displays passed values
Step 1 — Create activity_main.xml
Create:
res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Step 2 — Create MainActivity.java
Create:
MainActivity.java
package com.example.fragmentarguments;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity
extends AppCompatActivity {
@Override
protected void onCreate(
Bundle savedInstanceState
) {
super.onCreate(savedInstanceState);
setContentView(
R.layout.activity_main
);
ExampleFragment fragment =
ExampleFragment.newInstance(
"Example Text",
123
);
getSupportFragmentManager()
.beginTransaction()
.replace(
R.id.container,
fragment
)
.commit();
}
}
Step 3 — Create ExampleFragment.java
Create:
ExampleFragment.java
package com.example.fragmentarguments;
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.TextView;
public class ExampleFragment
extends Fragment {
private static final String ARG_TEXT =
"argText";
private static final String ARG_NUMBER =
"argNumber";
private String text;
private int number;
public ExampleFragment() {
// Required empty constructor
}
public static ExampleFragment newInstance(
String text,
int number
) {
ExampleFragment fragment =
new ExampleFragment();
Bundle args = new Bundle();
args.putString(
ARG_TEXT,
text
);
args.putInt(
ARG_NUMBER,
number
);
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(
@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState
) {
View view =
inflater.inflate(
R.layout.example_fragment,
container,
false
);
TextView textView =
view.findViewById(
R.id.text_view_fragment
);
if (getArguments() != null) {
text =
getArguments().getString(
ARG_TEXT
);
number =
getArguments().getInt(
ARG_NUMBER
);
}
textView.setText(
text + " " + number
);
return view;
}
}
Step 4 — Create example_fragment.xml
Create:
res/layout/example_fragment.xml
<?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"
android:gravity="center"
android:background=
"@android:color/holo_green_light">
<TextView
android:id=
"@+id/text_view_fragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Fragment Text"
android:textSize="22sp"/>
</LinearLayout>
How This Implementation Works
The workflow is:
- MainActivity creates Fragment using factory method
- Bundle stores arguments safely
- Fragment receives arguments using setArguments()
- getArguments() retrieves stored values
- UI displays received data
Why setArguments() Is Important
Using:
setArguments()
allows Android to automatically restore Fragment state during:
- Configuration changes
- Process recreation
- Navigation restoration
Common Mistakes Developers Make
1. Using Custom Constructors
Custom Fragment constructors can break lifecycle restoration.
2. Forgetting Empty Constructor
Fragments should always have:
public ExampleFragment() {
}
3. Accessing getArguments() Without Null Check
Always check:
if (getArguments() != null)
before reading Bundle values.
Modern Android Recommendations
Modern Android applications often use:
- Safe Args Navigation Component
- Shared ViewModel
- Jetpack Compose navigation
- StateFlow
- Parcelable data transfer
Bundle vs Shared ViewModel
| Bundle Arguments | Shared ViewModel |
|---|---|
| Good for initial data | Good for shared state |
| Lifecycle restoration friendly | Reactive UI updates |
| Simple implementation | Better for complex apps |
Modern Navigation Alternative
Modern Android apps commonly use:
- Navigation Component
- Safe Args Plugin
- Compose Navigation
These provide type-safe argument passing with better lifecycle handling.
FAQ
Why should Fragments avoid constructors with parameters?
Android recreates Fragments automatically using the default constructor.
Can Bundle store objects?
Yes. Bundle supports Serializable and Parcelable objects.
What is the modern recommended approach?
Navigation Component with Safe Args is the modern recommended solution for Fragment argument passing.
Conclusion
Passing data to Fragments using Bundle arguments and factory methods is the safest and most lifecycle-aware approach in Android development.
This pattern improves:
- Lifecycle safety
- Fragment restoration
- Code readability
- Reusability
Modern Android applications should combine Bundle arguments with Navigation Component, Shared ViewModel, and lifecycle-aware architecture for scalable Fragment communication.
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.