Android Fragment not attached to a context

Weidian Huang
4 min readMar 27, 2021

This is a common issue if we don’t take care of it in our application, and it is difficult to catch the issue during development. But once our app is deployed to production, sometimes we can see this kind of crash is reported.

This is an example of the crash log:

Simulate the issue

To simulate the issue, I created this simple application.

The application can simulate 2 different scenarios that could cause the crash.

  • Pop up dialog
  • Bottom sheet fragment

Pop up dialog

In this flow, when the button “SHOW POP UP” is clicked, it simulates an API calling to the backend, the backend returns an error and a dialog is shown.

Normal flow

Because the dialog is shown after an API call, it has some delay. During this period, the user may click the back button to exit the fragment, or the parent activity is recreated when the phone orientation is changed.

Crash when the user click back button
Crash when the photo is rotated

Bottom sheet dialog

In normal flow, the user selects some photos from Camera or Gallery, and imports them to the current app.

But if the user imports a lot of photos, and we need to do some processing on the photo, it could take some time, and the user can click back button at any time also. In this case, the application may be crashed.

Root Cause

From the fragment lifecycle, we know that if a fragment is detached, doesn’t mean it will be destroyed immediately. There are some cases that may delay the fragment being destroyed:

  • Button or view click listeners are still executing. For example, after clicking on a dialog button, there is another dialog shown. Until the final dialog is dismissed, otherwise we still consider the first click listener is executing.
  • Asynchronous tasks are not canceled properly when the fragment onDestroy() is called.
  • Other issues causing memory leaks, please refer to another article from me: https://weidianhuang.medium.com/how-to-avoid-memory-leak-android-and-jvm-languages-b5283c58fe1f

Let’s see the code for the above pop-up dialog.

There are 2 issues with the above code:

  • requireContext() can crash directly if the context is null
  • Calling getString(R.string.error_not_found) from fragment will crash if the fragment is detached,

Let’s see the code for another example of the bottom sheet fragment.

It looks nothing wrong, and we often do like this. But it could crash when the fragment is detached because we are calling getString(R.string.imported_photos_from_camera) and getString(R.string.imported_photos_from_gallery) from the fragment.

Solutions

To prevent these issues, firstly we need to remember:

  • Don’t do any time-consuming tasks inside the fragment or activity
  • Any time-consuming task, must be handled inside View Model and use LiveData to update the result back to the fragment or activity. Even it is just a BottomSheetFragment. Google has fixed a bug inside androidx library, so now the LiveData observers are not called after onDestroyView() is called inside the fragment. (https://bladecoder.medium.com/architecture-components-pitfalls-part-1-9300dd969808)

By doing the above, does that mean we are safe already? Unfortunately, NO. In the production environment, it could be complicated and we cannot predict the users’ behaviors. To avoid the issue, this is the method to check if the fragment is attached and the current context is not null.

Before showing the dialog, we can call this method. As a result, we can make sure we only show the dialog when the fragment is attached. Also getString() is called from the current context, it will be safe even the fragment is detached.

The same fix applied to the bottom sheet dialog.

Conclusion

It’s quite complicated sometimes to explain why the exception is thrown in the production app, but when you met this issue, what you need to do is just wrap checkIfFragmentAttached around the place it crashed.

--

--