Wednesday, January 22, 2020

How to Pass Data to a Fragment Using Bundle and Factory Method in Android

email this post Edit Post

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:

  1. Create a Bundle
  2. Add values into Bundle
  3. Call setArguments()
  4. 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:

  1. MainActivity creates Fragment using factory method
  2. Bundle stores arguments safely
  3. Fragment receives arguments using setArguments()
  4. getArguments() retrieves stored values
  5. 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.

No comments:

Post a Comment