Android. Detect if fragment is visible to user.

Kotlin is here)

Imagine that you have one activity and several fragments inside it, which you dynamically add, remove using FragmentManager
Few days ago in my project I realized that I can’t understand which fragment is currently visible to user. I need this because when app received notification from server I don’t want update fragments that are not visible now 
because it consumes processor time and UI will be less responsive. I want update only currently visible fragment.

So I need method that indicates that fragment become visible/invisible to user (lke Activity.onPause(), Activity.onResume())
Api that I need to handle notification in good way:

So I have this problem: I can’t find a method onBecomesVisible() in Fragment API. I thought that onPause() and onResume() will triggered but I realized that they’re connected with Activity lifecycle. So Activity wasn’t paused/resume -> this method’s won’t be called :(

First of all I tried to find solution in standard Fragment API. I had 4 fragments in stack one above another and method Fragment.isVisible and Fragment.getUserVisibilityHint() returned true for all of them. Funny story :)

My solution is to use one method for navigation and execute Fragment.setUserVisiblityHint(boolean) every time fragment’s
visibility changed. It looks like the following:

The client code looks like the following:

As you can see the main difference between usual method is that I manually cal from.userVisibleHint = false to mark that fragment is not visible to user. Now I know which fragments are not visible to user.

Another problem is to detect when fragment is visible to user. The easiest solution was to add code to.userVisibleHint = true to previous method but we will not cover case when user click back button (popBackStack() executes). To handle this case we need to listen to back stack changes and every time it’s changed get current fragment and execute `fragment.userVisibleHint = true`

I must say that have some bug that onBackStackChangedListener executed twice on support lib version 25.0.1. Update to 25.4.0 version and all will be all right.

Finally we can replace our func onBecomesVisible() with func setUserVisibleHint().

Of course need to say to prevent destroyed fragment not to receive notification we must unsubscribe from them in method onDetach()

And finally, I don’t like this call every time, but this is not enough functional for library so I just placed all this logic in class NavigationDelegate. So if you find this useful you can use this code.

Usage in client code:

Sample of code at github.