Android Fragments Tutorial: An Introduction with Kotlin

In this Android Fragments with Kotlin tutorial you will learn the fundamental concepts of fragments while creating an app that displays dogs breeds. By Aaqib Hussain.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 4 of 4 of this article. Click here to view the first page.

Binding Adapters

On the ImageView for the dog image you’ll notice the following tag:

imageResource="@{dogModel.imageResId}"

This corresponds to a binding adapter in the DataBindingAdapters.kt file.

  @BindingAdapter("android:src")
  fun setImageResoruce(imageView: ImageView, resource: Int) {
    imageView.setImageResource(resource)
  }

A binding adapter allows you to perform actions on an element which are not supported by default data binding. In your case, you are storing a resource integer for the image to display, but data binding does not provide a default way to display an image from an ID.

To fix that, you have a BindingAdapter that takes a reference to the object from which it was invoked, along with a parameter. It uses that to call setImageResource on the imageView that displays the image of the dog.

Now that your view is set up, replace newInstance() in DogDetailsFragment with the code shown below:

private const val DOGMODEL = "model"

fun newInstance(dogModel: DogModel): DogDetailsFragment {
  val args = Bundle()
  args.putSerializable(DOGMODEL, dogModel)
  val fragment = DogDetailsFragment()
  fragment.arguments = args
  return fragment
}

A fragment can take initialization parameters through its arguments, which you access via the arguments property. The arguments are actually a Bundle that stores them as key-value pairs, like the Bundle in Activity.onSaveInstanceState or the Activity extras from intent.extras.

You create and populate the arguments’ Bundle, set the arguments and, when you need the values later, you reference arguments property to retrieve them.

As you learned earlier, when a fragment is re-created, the default empty constructor is used— no parameters for you.

Because the fragment can recall initial parameters from its persisted arguments, you can utilize them in the re-creation. The above code also stores information about the selected breed in the DogDetailsFragment arguments.

Add the following import to the top of DogDetailsFragment.kt:

import com.raywenderlich.android.eldogo.databinding.FragmentDogDetailsBinding
Update note: You may need to rebuild the project for FragmentDogDetailsBinding to be available

Now, replace the contents of onCreateView() with the following:

// 1
val fragmentDogDetailsBinding =
        FragmentDogDetailsBinding.inflate(inflater, container, false)

// 2
val model = arguments!!.getSerializable(DOGMODEL) as DogModel
// 3
fragmentDogDetailsBinding.dogModel = model
model.text = String.format(getString(R.string.description_format), 
  model.description, model.url)
return fragmentDogDetailsBinding.root

Breaking it down:

  1. Inflate the view using FragmentDogDetailsBinding. Since you want to dynamically populate the UI of the DogDetailsFragment with the selection, you grab the reference to the FragmentDogDetailsBinding.
  2. Get the DogModel from the arguments.
  3. Next, you bind the view dogModel with the DogModel that you’ve passed to DogDetailsFragment.

Finally, you need to create and display a DogDetailsFragment when a user clicks an item, instead of showing a toast. Open MainActivity and replace the logic inside onDogSelected with:

// 1
val detailsFragment =
     DogDetailsFragment.newInstance(dogModel)
supportFragmentManager
     .beginTransaction()
     // 2
     .replace(R.id.root_layout, detailsFragment, "dogDetails")
     // 3
     .addToBackStack(null)
     .commit()

You’ll find this code is similar to your first transaction which added the list to MainActivity, but there are also some notable differences. In this code you:

  1. Create a fragment instance that includes some nifty parameters.
  2. Call replace(), instead of add, which removes the fragment currently in the container and then adds the new Fragment.
  3. Call another new friend: the addToBackStack() of FragmentTransaction. Fragments have a back stack, or history, like Activities.

Navigating the Fragment Back Stack

The fragment back stack is not independent of the activity back stack. Think of it as an extra stack of history on top of that of the host activity.

Fragments and back stack

When you navigate between activities, each one gets placed on the activity back stack. Whenever you commit a FragmentTransaction, you have the option to add that transaction to the back stack.

So, what does addToBackStack() do? It adds the replace() to the back stack so that when the user hits the device’s back button it undoes the transaction. In this case, hitting the back button sends the user back to the full list.

The add() transaction for the list omits calling addToBackStack(). This means that the transaction is part of the same history entry as the entire activity. If the user hits the back button from the list, it backs the user out of the app.

Now, build and run and you should see details about each breed when you tap on them:

Screenshot with breed details

With that you’re done! You now have an app El Dogo that displays details about the dogs breeds.

Where To Go From Here?

You can find the Final Project for this tutorial by clicking the Download Materials button at the top or bottom of this tutorial.

There is a lot more to learn and do with fragments. Like any kind of tool or feature, consider whether fragments fit your app’s needs and, if they do, try to follow best practices and conventions.

To take your skills to the next level, here are some additional things to explore:

.

  • Use fragments within a ViewPager. Many apps, including the Play Store, utilize a swipeable, tabbed content structure via ViewPagers. You can learn more in our ViewPager tutorial
  • .

  • Use a more powerful, advantageous DialogFragment instead of a plain vanilla dialog or AlertDialog.
  • Play with how fragments interact with other parts of an Activity, like the app bar.
  • Create adaptive UIs with fragments. In fact, you should run through Adaptive UI in Android Tutorial.
  • Use fragments as part of the implementation of a high-level behavioral architecture. You can take a look at Common Design Patterns for Android as a good starting point to get the architecture ball rolling.
  • To learn more about Data Binding check this reference.

We hope that you’ve enjoyed this tutorial. If you have any questions or comments, please join the forum discussion below!