Fragments in Android

Abhishek Pathak
7 min readNov 18, 2022

--

What is fragment?

It represents the UI portion of application screen. It is part of Android Jetpack libraries. A fragment manages it’s own layout, it’s own lifecycle, can also handle the input from UI and represent the outcome.

  • Fragment can’t live / create on their own- They must be hosted by an activity.

Benefits of using fragments

  1. Reusability : As here below situation is we need a design having a common header and footer for the different screens and only changeable are is a content area so we can replace all the contents by different fragment.

2. Adaptiblity & Modularity: As here you can see below, I have 2 different screen sizes one is mobile in left and tablet in right, now same app if we inflater the same UI that is not going to be User friendly so fragments allows us to develop the adaptive UI according to screen type sizes like her i made a single list with bottom appbar for list of features while in tablet, i have menus of features with 2 list of recyclerview data in grid.

What are the lifecycle methods of Fragment?

We can interact between multiple part of UI using fragments via multiple ways. so it is very convenient to use fragments over activities to make a more easy interactive UI design implementation.

Lifecycle methods

  • onAttach(): attaches the fragment onto the host activity.
  • onCreate() : here fragment got created.
  • onCreateView(): here fragment views got created.
  • onActivityCreated(): this will help to initiate the view but now it got deprecated. Alternative of this lifecycle method is onViewCreated()
  • onStart(): it invokes when fragment got visible.
  • onResume(): this method invokes when fragment start interacting.
  • onPause(): this method invokes when fragment stop interacting.
  • onStop() : this method invokes when fragment no more visible.
  • onDestroyView(): this method destroys the view of it.
  • onDestroy(): this method invokes to destroy fragment.
  • onDetach(): this method invokes to detach reference with hosted activity.

How do we use Fragments?

Basically we have two ways to use fragments.

  1. add fragment statically : add a fragment tag inside activity and set name to the fragment and give id and ready for use it.
<fragment
android:id="@+id/music_fragment"
android:name="com.mvvm.fragmentsdemo1.SecondFragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

2. add fragment dynamically :

In adding a fragment dynamically means we have to set the supportFarmentManager to begin transaction of fragment by using methods like add() or replace() and lastly we have to call commit method to initiate the transaction.

//dynamic way of adding fragment
supportFragmentManager
.beginTransaction()
.replace(R.id.senderFragment, senderFragment)
.commit()

3. Using Navigational component and set the fragment graph.

Advantages of Using Fragments?

  • Modularity : Diving complex activity code across fragment for better UI performance and maintenance.
  • Reusability : Placing behavior or UI parts into fragments that multiple activities can share.
  • Adaptability : Representing each sections of a UI as different fragment and utilizing the different layout on screen orientation or size.

Add Vs Replace Fragments

  • So add() method keeps adding fragments on top of the previous fragment in the FragmentContainer.
  • While replace() method clears all the previous fragment from container and then add it in FragmentContainer.

How do we implement fragment in Android development?

Let’s take a real-time use case of fragments like a login/register screen have two fragments one for login and another for register. MainActivity is the host activity to keep these 2 fragments on the screen according to the requirement.

  • Make a common util for replace and add fragment method using extension function concept
package com.learning.loginandregistrationusingfragments
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentTransaction
fun AppCompatActivity.addFragment(containerId: Int, fragment: Fragment) {
supportFragmentManager.inTransaction { add(containerId, fragment) }
}
fun AppCompatActivity.replaceFragment(containerId: Int, fragment: Fragment) {
supportFragmentManager.inTransaction { replace(containerId, fragment) }
}
inline fun FragmentManager.inTransaction(func: FragmentTransaction.() -> FragmentTransaction) {
beginTransaction().func().commit()
}
  • Make UI for login fragment screen
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="300dp"
android:layout_gravity="center"
android:layout_margin="10dp"
android:background="#F3FBFF"
android:padding="10dp">

<TextView
android:id="@+id/txtLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="cursive"
android:gravity="center"
android:text="@string/login_here"
android:textColor="@color/black"
android:textSize="32sp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/edtEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:hint="@string/enter_email"
android:textColor="#130000"
android:textColorHint="#670404"
android:textSize="23sp"
app:layout_constraintTop_toBottomOf="@+id/txtLogin" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/edtPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:hint="@string/enter_password"
android:inputType="textPassword"
android:textColor="#130000"
android:textColorHint="#670404"
android:textSize="23sp"
app:layout_constraintTop_toBottomOf="@+id/edtEmail" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="#D61D1D"
android:fontFamily="monospace"
android:hint="@string/enter_email"
android:text="@string/login"
android:textColor="#FFFFFF"
android:textSize="23sp"
app:layout_constraintTop_toBottomOf="@+id/edtPassword" />

</androidx.constraintlayout.widget.ConstraintLayout>
  • make UI for register screen
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="450dp"
android:layout_gravity="center"
android:layout_margin="10dp"
android:background="#F3FBFF"
android:padding="10dp">

<TextView
android:id="@+id/txtLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="cursive"
android:gravity="center"
android:text="@string/register_here"
android:textColor="@color/black"
android:textSize="32sp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/edtName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:hint="@string/enter_name"
android:textColor="#130000"
android:textColorHint="#670404"
android:textSize="23sp"
app:layout_constraintTop_toBottomOf="@+id/txtLogin" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/edtAge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:hint="@string/enter_age"
android:textColor="#130000"
android:textColorHint="#670404"
android:textSize="23sp"
app:layout_constraintTop_toBottomOf="@+id/edtName" />

<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/edtEmail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:hint="@string/enter_email"
android:textColor="#130000"
android:textColorHint="#670404"
android:textSize="23sp"
app:layout_constraintTop_toBottomOf="@+id/edtAge" />
<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/edtPassword"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="monospace"
android:hint="@string/enter_password"
android:inputType="textPassword"
android:textColor="#130000"
android:textColorHint="#670404"
android:textSize="23sp"
app:layout_constraintTop_toBottomOf="@+id/edtEmail" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btnLogin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="#D61D1D"
android:fontFamily="monospace"
android:hint="@string/enter_email"
android:text="@string/register"
android:textColor="#FFFFFF"
android:textSize="23sp"
app:layout_constraintTop_toBottomOf="@+id/edtPassword" />

</androidx.constraintlayout.widget.ConstraintLayout>

here you can get the full source code.

How do we communicate between the fragments?

Task : We are going to implement an task for achieving a communication between fragment

Scenarios based on Fragment lifecycle

all fragment lifecycle methods got logged here
  1. When app launched then fragment lifecycle methods.

2. When fragment launched then pressed back button.

3. When app launched with hosted activity and a fragment on it.

4. When app launched with hosted activity and a fragment then pressed back button.

If Android version ≥ 12 then

If Android version ≤ 12 then

Reference of check of why <12 android Version is here android official doc

5. if actvity is root activity and then the fragment is also got attached on it then then what will happen if we take the activity from the recent apps

6. Root activity added a Fragment on it and then fragment is adding a child fragment on it so the lifecycle will be below

Bonus :

How to check that lateinit property is Initialized or not inside fragment easily?

/* 
On Kotlin 1.2 and up, we can quickly check whether a lateInit property has been initialised
or not using a reflection based API.
*/
if(::yourVaiableName.isInitialized){
//use your variable name without a worry point of having crash of app by unInitialized lateInit property
yourVaiableName.doSomethingAsPerBusiness()
}

Send data from activity to fragment using Bundle

Step 1: Prepare the data in the Activity In your MainActivity, create a Bundle and add the data to it:

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

// Create a Bundle and put data into it
val dataToSend = "Hello from Activity!"
val bundle = Bundle()
bundle.putString("dataKey", dataToSend)

// Create a new Fragment instance and pass the Bundle
val myFragment = MyFragment()
myFragment.arguments = bundle

// Load the Fragment into the container
supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, myFragment)
.commit()
}
}

Step 2: Receive the data in the Fragment

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView

class MyFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val rootView = inflater.inflate(R.layout.fragment_my, container, false)

// Retrieve the data from the arguments Bundle
val arguments = arguments
if (arguments != null) {
val receivedData = arguments.getString("dataKey")
val textView = rootView.findViewById<TextView>(R.id.textView)
textView.text = receivedData
}

return rootView
}
}

Send data from fragment to activity

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button

class MyFragment : Fragment() {

// Define the interface to communicate with the Activity
interface OnDataListener {
fun onDataReceived(data: String)
}

private var onDataListener: OnDataListener? = null

override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val rootView = inflater.inflate(R.layout.fragment_my, container, false)

val sendButton = rootView.findViewById<Button>(R.id.sendButton)
sendButton.setOnClickListener {
// Send data back to the Activity when the button is clicked
onDataListener?.onDataReceived("Data sent from Fragment!")
}

return rootView
}

// Function to set the listener
fun setOnDataListener(listener: OnDataListener) {
onDataListener = listener
}
}

Step 2: Implement the interface in the Activity

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity(), MyFragment.OnDataListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val myFragment = MyFragment()
myFragment.setOnDataListener(this)

supportFragmentManager.beginTransaction()
.replace(R.id.fragment_container, myFragment)
.commit()
}

// Override the onDataReceived method to handle data from the Fragment
override fun onDataReceived(data: String) {
// Handle the data sent from the Fragment
// For example, you can show it in a Toast or perform any other action
// In this example, we'll just log the data received
Log.d("MainActivity", "Data received: $data")
}
}

In this example, when the button inside the Fragment is clicked, it will trigger the onDataReceived method in the hosting Activity, passing the data "Data sent from Fragment!". You can then handle this data in the Activity as required.

If you found this article valuable, please show your appreciation by applauding it 👏. Your feedback is important to me, so please share any suggestions for improvement in the comments section.

Let’s stay connected on Linkedin , GitHub to continue learning and collaborating together.

--

--