Android Fragments and Transactions

Problem

Sometimes it is confusing how fragments work in Android and interesting side effects like:

  • Why have Fragments empty constructors?
  • Why shouldn’t I pass state variables like they are?
  • Why do I need this Fragment transactions?
  • What does addToBackStack mean and do I need it?
  • Why is sometimes the Activity null in my fragment?

Overview

Fragments are used to wrap functionality into an own reusable UI element. The life cycle is well documented by google. More interesting is, that android may recreate fragments during it’s life cycle which leads into interesting implications.

Furthermore Fragments are not directly added an visible, as requesting them to show only queues this task. Nevertheless they will be shown later on.

Sometimes it is also confusing that creating an fragment inside a fragment will always pass the common activity of both fragments into it.

Dynamic recreation

As android can recreate the fragment during the resume process of an activity. As so state in member variables needs to be persisted. In general fragments should always be created using a bundle or be dismissed by the activity in the onPause method:

As long as the fragment is restored, the activity of it may be null. As so it may happen that own threads still running in the fragment may encounter null pointer exceptions.

The easiest way is either:

  • Stop all running threads in the onPause
  • Remove all listeners for the time being, but keep the threads, e.g. if you want to keep a socket connection open
  • save in a boolean variable the fact that your fragment was paused and wait for the resume

Hide and show DialogFragments

Showing a fragment is straight forward, by calling the show method. Now we can pass a second parameter, which is used to find this fragment later on. We can decide by storing the reference in a field variable or just to remember the name. Usually the last is the better approach.

But how now correctly to dismiss the fragment?

The above code example works for any kind of fragment. Of course it is also possible to cast the fragment into a DialogFragment and invoke the dismiss method.

addToBackStack or not?

The main purpose of the addToBackStack method in the fragment transaction is to allow the user to use consistently the back button. If we modify the code above to:

Then the user may open the dialog again with the back button on the phone. This is very interesting if you move between different fragments / dialog fragments. E.g.: you have an edit dialog fragment which opens a date time picker dialog. Then you can remove the detail dialog fragment and add the date picker fragment in one transaction. As soon the user hits the back button the detail dialog fragment is again visible.

As the name already indicated, it is a stack of view states, each change to the view is seen as a transaction. The user may pop the stack by using the back button.

In short:

  • Cancel or just close the dialog / fragment –> don’t add it to the back stack
  • Navigate to a Fragment like to an activity –> add it to the back stack, so the user can go back

Prevent closing of a Dialog Fragment using the back button

After the fragment was created set cancelable to false.

Is isVisible or isAdded reliable?

This happens to be the most tricky question. As showing a dialog will not always show the dialog immediately. It only schedules the show operation for the Fragment Manager.

As soon you happen to see errors like:

The first solution by just calling getFragmentManager().executePendingTransactions() wont work.

The reason is typically a multithreading issue, calling/ scheduling multiple show operations for the same fragment from a background thread. The best fix would be to find why this is called multiple times and check if this can be avoided. If not, then an AtomicBoolean could be the rescue e.g.:

Using the AtomicBoolean enables you now to verify in a multithreaded environment if show was already called on the dialog.

Paul Sterl has written 17 articles

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">