How to save View's state after pause? - android

When my app completes some async tasks, it notifies UI about it.
For example:
user clicks on "Do work" button inside of my application -> async work started
and switches to another app -> state is saved
then "work" inside my app is finished and View-s updated -> async work finished (note that my activity is paused)
User rotates the phone and then navigating back to my app
problem: state is restored and View's state updated in 3 step is gone while work was finished!
How to deal with such cases?
Is there any way to save settings after app is paused?

Consider using MvpQueuingBasePresenter or Model-View-Intent which deals better with lifecycle related things.

I think you should update the state of the view in onResume method from that activity.
ref: https://developer.android.com/guide/components/activities/activity-lifecycle.html

Related

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:
override fun onResume() {
super.onResume()
tryToLoadDataAgainAndReloadAlotOfImageViews()
}
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?
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!
You can use the isFinishing method to check if the activity is in the process of finishing before calling tryToLoadDataAgainAndReloadAlotOfImageViews() in onResume()
try using Glide.
dependencies :
//Glide
implementation("com.github.bumptech.glide:glide:4.12.0")
kapt("com.github.bumptech.glide:compiler:4.12.0")
As per the official documentation
Glide is a fast and efficient open source media management and image loading framework for Android that wraps media decoding, memory and disk caching, and resource pooling into a simple and easy to use interface.

How to handle data changes and view updates when activity is in background

I have an App with 2 activities A -> B. From B the user can update data being displayed by A, so I want A to show fresh data when the user navigates back (actually not so simple, some network involved so data can be updated at any time).
The activities are listening to ddbb changes so the views can be updated when data changes. Problem is data can change while activities are in background, so I am not sure when and how i should listen for changes. I can think of two approaches:
Listen for changes during the whole Activity lifecycle (onCreate - onDestroy) and just update the views when the data changes. This will update views from background activities.
Listen for changes only when the Activity is being active or displayed (between onStart/onStop or onResume/onPause) and force a view update every time the activity comes to the foreground (since changes might have happened while activity wasn't listening).
Mixed approaches; keep the listeners the whole lifecycle but only update views when activity comes to foreground.
Im not sure which is the correct way to handle data observing while in background.
Option 2 sounds more reasonable, but having to update the views when the activity comes to foreground may lead to UI lag right when the user starts interacting with the activity.
Option 1 will cause a lot of updates every time data is updated.
Thoughts on this?
You can choose any of the three options that suits your particular use case. Though I will say that the conventional use is with start/stop. onStart says that the activity is visible to the user in some way (either fully or partially) and onStop says that the activity is definitely not visible. So if you don't care to update the UI while the activity is not showing at all, use these lifecycle states.
You just may need to be prepared to capture data that you may have missed while the activity was stopped before it gets started again (for example, if the user pressed the home button, then came back to the activity via the task switcher. So performing your query again and rebuilding the contents of views from scratch may be necessary.

Cancel Action in onPause

In my login Activity, just after the use log in, I sync data and create several tables in sql.
If the user open another app before this process finish, I want to cancel it and delete tables.
I thought I could put it in onPause or onStop, but then, when the process finishes and go to the dashboard activity, onPause or onStop should be called, and I don't want this.
I assume the solution is simple, but I can't figure out how to solve it.
Any idea?
The logic behind your solution is straightforward - create a flag (say for example shouldRollback) to true when you start your transactions. Once your transaction are successfully completed, you set this flag to false. In your onPause() method, simply check for this flag. If it is true, you know you need to roll back the changes.
I would only suggest this if this is your requirement. Personally, I would process all database operations in a background thread. The thread can run in the background even if other applications are opened. There will be too much overhead (if you have a large number of transactions) to keep rolling back inserts. You could use the transaction methods from the SQLiteDatabase object to automatically roll back changes if they were not completed successfully.

Application brought back to foreground with wrong activity

I have a problem with my application when it is brought back to the foreground in the case the phone went low on memory while the application was hidden:
The class inheriting from Application is re-created (onCreate is called again), thus losing data it held before. The Activity which is restarted is not the one tagged as main action in the Manifest, but the last one that was active. This is a problem as the main activity, from which the user logs in, is the one responsible for filling in the Application subclass' data and I can't fill it in later.
Is there any way to tell the application to restart at the main activity instead of the latest one in this case ?
You could check in onResume() if the user is logged in. Means that you check if your Application data is filled. If this is not the case, finish the activity and start your first Application.
The user expect to return to the latest activity, so a general "always start first activity" would upset the user...
you could keep the data by implementing methods such as onPause() and onResume()
Check this link out: http://developer.android.com/reference/android/app/Activity.html
this answer might also be helpful: onSaveInstanceState () and onRestoreInstanceState ()

Android - Detect 'app became active' from multi-tasking

I am trying to detect if my app became active from multi-tasking and display a dialog.
The use-case is something like this: User is using the app -> Hits the home button -> Does something -> User taps on the app again
As expected, the last activity the user was on is being shown.
I want to display a dialog when this happens. I used onRestart() for the same and it works. Only problem is, even when the user goes to some activity in the app and then hits back, the dialog is being displayed.
I went through the activity lifecycle several times, but couldn't figure out the solution. Any ideas?
Well, you can tell the foreground application using the technique outlined in Determining the current foreground application from a background task or service: look for getForegroundApp. You could run a timer that checks periodically to see if the app is foreground, and if its not then set a variable after a suitable delay (to make sure you don't happen to hit it in the wrong order when switching Activities). Clear the variable in onStart, and if onCreate of the rooth Activity is ever called you know that the app just became Active.
I achieved this by setting a flag in Shared Preferences in onStop() and cleared it in onDestroy().
Then I overrided the Back button to clear the flag whenever it is pressed. This solves the problem I had stated.
Now in onRestart(), if the flag is true.... I display the dialog.
I know it is not the most elegant solution but does the job! Hope this helps somebody.

Categories

Resources