Android onResume Hell

You could say I entered fragment onResume hell last night. In my android app I am using a ViewPager to scroll between various to-do list for a given project. Each list is a Fragment pretty much as set up in one of the starting skeleton apps defined in Android Studio.

This is all well and good except for one of the features is you can move items between various lists. Making it disappear is pretty trivial as you have easy access to the ArrayAdapter for the ListView you are working with. At that point you don't really have a way to tell the list that has just got a new item in you list and you need to redraw.

Eventually I hatch the idea that I will use the onResume() method on each fragment to update the view with any changes. That is call the notifyDataSetChanged() method on the ArrayAdapter class for the ListView.

The weird thing is onResume was not being call as the fragment was being brought into view. Rather it was being called when we moved to the tab next to it. This meant would sometimes not update the view correctly. It also meant my mental model of ViewPager was not correct and this was much worse than have a not updating bug.

My mental model for ViewPager is it would store a series of Fragments and allow you to seamlessly move between them, either by swiping, touching tabs or some other method depending on how you set it up. My mental model was all the Fragments were created at the start and onResume and onPause would all be called when the fragment was brought into view of the user or left the view.

Ok, I really knew that there would be caching involved for fragments and they would be recreated/deleted at various times. I assumed this would all be transparent and would not affect when onResume/OnPause are called.

I was wrong. As far as I can tell this is what is happening. ViewPager stores up to 3 fragments by default. The current one being viewed, the next and the previous one. You may be able to configure the number 3...

When you swipe, or some how move, to the next one, the old previous one gets its onPause method called on it as it leaves the cache. Neither onPause or onResume are called for what was the current one or what was the next one if you see what I mean.

Now that we have moved forward through the tabs the ViewPager has to get the next fragment ready for us, just in case we swipe again. This mean OnResume is called for that fragment.

The TL,DR for this is onResume/OnPause are called on fragments in a ViewPager when they enter/leave the cache not when the enter or leave the sight of the user.

I am betting this is in the docs somewhere (Android docs are pretty good) but it was a pain point for me for a few hours.

So if you need to trigger an update to a fragment as it is being brought into sight when using a ViewPager what should you do?

My solution was use the onPageSelected of the FragmentPagerAdapter, Get hold of the fragment about to be displayed and manualy call onResume on it.

See this StackOverflow question.

Comments

Popular posts from this blog

Fast iteration

September 2018 Start of Geek Month

Quick(ish) Sweet Potato and Tuna Steak