Resolved: Android kotlin unintended onResume when user clicked permission dialog

In this post, we will see how to resolve Android kotlin unintended onResume when user clicked permission dialog


I am maintaining a simple Android kotlin app that only has one MainActivity.
The app has a lot of images. We want to reload the data and images when user navigate away and then return to our app, this works so far:
However this produces one unpleasant side effect, for example:
  • User launch the app
  • onResume fired, we load data and refresh all images (corrrect)
  • App shows permission dialog to grant GPS locations
  • User click accept
  • permission dialog dismisses
  • onResume fired again, all data reloaded and images reloaded again.

This will looks like a glitch as all images are reloaded twice in a short period of time. I understand that I may set booleans here and there before showing permission dialogs to resolve this, but it feels like a hack and possibly buggy code.
Is there any elegant way to resolve this? For example, detecting onResume is coming from another app, or coming from internal permissions dialogs?

Best Answer:

We want to reload the data and images when user navigate away and then return to our app

What do you mean by this exactly? Are you talking about the app disappearing from the screen? (e.g. the user switches to another app, or hits the home button, or turns off the screen.) If so, do your refreshing in onStart instead of onResume, then it’ll only fire when the app becomes visible again.
But if you want to handle things like multi-window mode, where your app is visible but might not have focus, then you’ll need to look into detecting that when your app hits onPause, and maybe storing a flag onResume can check.
Basically Android’s Activity and Fragment lifecycles have a couple of paired callbacks, onPause/onResume and onStop/onStart.
When your app is no longer in the foreground, but still visible, it moves to the PAUSED state. If it remains visible, but then moves to the foreground, it moves from PAUSED to RESUMED by calling onResume. This is what’s happening with your dialog – because it’s displayed over your Activity, the Activity is paused until the dialog is dismissed, at which point it calls onResume. So what’s happening is by design!
But if your app is becoming invisible (i.e. it’s not on the screen anymore) then it first moves to the PAUSED state (if it’s not already), and then it moves to STOPPED and you get the onStop callback. When it returns to the foreground, onStart will be called, followed by onResume. (This is also what happens when the Activity/Fragment is (re)created of course!)
So you need to handle things in the appropriate lifecycle callback. It sounds like your needs are better met by having this stuff handled in onStart, since that only gets called when the Activity/Fragment appears. onResume can be called more often, since it’s possible for the component to enter the PAUSED state (onResume is called when it’s “unpaused”) without moving to the STOPPED state – like with dialogs.
Like I said, if you want to handle multi-window mode that’s more complicated, and the lifecycle behaviour depends on API level, so you’ll have to look into that!

If you have better answer, please add a comment about this, thank you!