What happens to activities and fragments when app is in background - android

I understand the basic Lifecycle of Activity/Fragment but sometimes, when user puts the app in background state for long time I'm not sure what's going to happen when he opens it again. Recently I've encountered a bug: User gets nullpointer exception by calling method of a view saved in class variable (textView = findViewById(...)), inside fragment's OnResume method. The variable is set in OnViewCreated(). Is that possible that over long period of time fragment might lose it's fields due to lack of memory? When onResume() will be called and when onCreate()?

If the app is in background for a long time its process will be killed by OS, or if the device is running low memory. To test how your app works under these conditions use flag "Do not keep activities" in Developer options on your device. In the described case onCreate will be called when Activity will come to the foreground.
If the process is not yet killed then onResume will be triggered. Normal variables persist, but the problem is that you can never be sure when you're calling onResume and when you're calling onCreate (since you have no control over when Android just goes and tosses stuff on the stack out the window... anything not currently being used is eligible for destruction).
So my solution is to add a null check with if condition: if the variable is null then initialize and perform actions, if not then just preform actions.

Related

I have a trouble in Fragment life cycle and need a resolution to come out of it

I have done ample research on this, and there is not one clear solution on the problem.
In the life-cycle, particularly in the Fragment life-cycle, following Exception comes any moment after onPause().
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
My logic says, that to continue with the current fragment, after it reaches this state, I have to restart the activity and again point back to the intended fragment using Intent.
I want to be clear on what is happening and what should be real solution to deal with it.
I need to know the pros and cons of this mechanism; its importance in Fragment or Activity life-cycle.
Also, if I am changing the Windows Feature in onCreate to not to go to sleep, unless if the user has manually pressed the home button, will still the activity will go to this state?
This exception happens when you're trying to add/remove/replace/interact in any other way with a Fragment inside the Activity when it's paused.
Which means Activity will not be able to restore it's state (restore the state of a Fragment which has been changed) if it will be destroyed right away.
Best solution here, is to check that Activity is NOT paused during the interaction with a Fragment.
Another option is to use commitAllowingStateLoss() to interact with Fragment transaction, with a risk of losing it's state.
See:
https://developer.android.com/reference/android/app/FragmentTransaction.html#commitAllowingStateLoss()
In a perfect world you should analyze each crash carefully and add checks to verify that you interact with fragments only when Activity is up and running.
A better explanation is presented in a new Android developer reference and guide documents for using JetPack Life Cycle Listener.
https://developer.android.com/topic/libraries/architecture/lifecycle#kotlin
The library makes the components Activity Life Cycle aware. That means you do not require an abstract baseActivity class which overrides every life cycle callback, and record that state in a boolean variable. LifeCycle listener will do it for you.
All you have to do is stop introducing a new fragment or stop any Loader that updates the UI when its response returns. The right time to do this is before onStop or onSavedInstance state is called, and your components will be made aware of it.
It clearly states that after the onSavedInstancState or onStop is called the UI becomes immutable till the onStart of the Activity is called again. Sometimes you have to call restart the same activity using NEW TASK and CLEAR TASK flags using intent, when this state occurs and there is no chance that otherwise onStart is going to be called.
Happy Coding :-)

what happens to an activity when in pause state?

When an Activity goes in pause state, an instance of it remains in the Activity stack that is managed by operating system. And I know after a while, it destroys the instance. Now my question is whether the onDestroy() method is called when operating system destroys the Activity instance after a long while?
Like if I put a Toast inside onDestroy() method, that will be shown when the Activity instance gets destroyed by OS? (I know it will be shown by pressing back button).
The nature of this question makes it hard to test because sometimes it takes a day or more for OS in order to destroy an Activity instance in stack.
There is no guarantee that it will be called. You can see Activity#onDestroy for that.
Note: do not count on this method being called as a place for saving data! For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here. This method is usually implemented to free resources like threads that are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.
By simply killing it could be e.g. a System.exit call or something similar where it skips the lifecycle hooks.

What we should do in onStart, OnResume, OnPause

Hi I have gone though activity lifecyle on many threads, but I could not find what we should do in onStart, onResume, onPause method of the activity.
In the onStart() method, you add code that's relevant at the beginning of the activity.
Let's say, you have an app that reads the temperature of the device's battery. You'll want to have an initial value, so as to show the user.
So in the onStart(), you'd add code that goes ahead and fetches the information you'd need, and displays it for the user, before your timer (for example) goes and reads the information a minute later.
The onPause() method is called before the application goes in to the background.
To stay with our example, in the onPause() method, you'd save the last recorded temperature to the device; so you can show a comparison when the user next opens the app.
The onResume() method is called when the application is brought back to the foreground (i.e.: you've gone to the task manager, and tapped on your app to show it again).
Again, staying with the going example; in the onResume() method, you'd go ahead, read your saved data, load fresh data, and show a comparison of the two in the application.
Then, when your timer ticks next, only fresh data will be shown.
Your question is a bit vague, so answer might not be super specific..
I would say there are no strict "rules" around what we should do in corresponding activity lifecycle methods.
In fact, you can do nothing there (just make sure you call super method if you decided to override those). I.e. your custom activity might not even override these methods - it will work just fine.
onStart, onResume and onPause methods are just hints to you about activity lifecycle change, so you can react accordingly, i.e. start/stop specific to your activity operations at the appropriate time.
For instance, when onResume is called it means that activity became fully visible to the user, so you might want to start some animation (if necessary)
Again, you are not obligated to put any code in there.
Usually most of the operations are performed within oncreate and onresume.
However for your info let me brief it out,
Onstart- this is called after Oncreate, once activity is visible to the user, if you want to perform some operations before the visibility do it in Oncreate, because most of codes should be operated before user views the activity.
OnResume-Be cautious on Onresume is it is quite tricky it will be called whenever you activity is brought to foreground.
Onpause-Called before Onresume, codes wont be executed here, so strictly avoid adding codes in Onpause instead add inside Onresume.
Hope it helps,

Why is this happening? saveInstanceState=null

The above issue arises once in two debug. And the weird thing is app doesn't crashes, it stops responding.
What does this mean? And what wrong is happening inside?
You should really read the documentation on this, it will help you out a lot.
The savedInstanceState field is set when your Activity is being re-created from a previous instance. This happens e.g. when the device changes orientation or when the user navigates away, and then navigates back to your Activity. When the field is set, this allows you to restore the state of the Activity as the user left it.
The savedInstanceState field is null when your Activity has no previous state to restore from.
When your Activity is about to be destroyed, you can add variables to the savedInstanceState by overriding onSaveInstanceState(Bundle bundle) in your Activity, and adding them to the Bundle. The next time your Activity's onCreate(Bundle savedInstanceState) will be called, the fields you set in the onSaveInstanceState() will be available to you in the Bundle.
Finally, the "application not responsive' dialog is shown when you do too much work on your application's main (UI) Thread. However as pelotasplus mentioned this may also occur when you connect the debugger. If this dialog is shown when you have the debugger attached I wouldn't worry about it. However, if this dialog is shown during normal use of your app, this indicates you perform too much processing on the main Thread and you should move the heavy lifting to background threads, e.g. by using Loader, AsyncTask, IntentService, Thread or any of the other options available for this.
There are two things here, first of all
saveInstanceState = null
you see in your debugger is nothing unusual. Sometimes it's null, sometimes it's not. This is how Android framework works ;-)
For more information about that go read official docs about Activity lifecycle: https://developer.android.com/training/basics/activity-lifecycle/recreating.html#RestoreState
Second thing is that ANR (application not responding) window which happens a lot when debugging your apps. Just press WAIT and you are good to go.

How to know when an application finished?

I need to know when an application finishes to stop all the local services that it starts.
How can I do it?
You could try using onDestroy() (not recommended, though) to know when Android is cleaning your app from the memory. or can also use onStop() to know when the Activity is being sent in the background.
Do implement these two methods in the first activity of the Activity stack.
Lets see if it helps, since I also haven't tried it so far.
One idea is to use BoundService despite the fact that it's your app own service. By definition Bound Service stops when the las connection is dropped.
Another idea would be to define count in Application object (you can override global Application object). You can increment the count in each onResume and in decrement in each onPause.
You could use try / finally on the main function and do the service clean up in the final block
You could use object finalizer to issue shutdown commands. You wont know exactly when it happens since the Garbage collector will run at its own pace, but you do know it will happen eventually.
I am now solving the same problem, I have an Idea and will implement it:
1.static variable called (String currentShownActivity).
2. in every Activity (onResume() ) I fill the variable with activity name). So when I navigate between the activities the currentShownActivity variable changed and carry the current activity name.
3. on every onPause(), set flag that indcate the activity onPause() called (i.e boolean IsPauseCalled)
4.in onStop () check IsPauseCalled, and the activity name.
if the activity onPause called and the name in currentShownActivity not changed (that mean we leave the activity to "no activity") and that mean [home] key pressed.
the integration way to know the the application is not running Check onDestroy of the main activity.

Categories

Resources