What is the Difference between onResume() and onPostResume() in Activity Life Cycle? - java

While Learning Activity LifeCycle in Android, I am confused about these two methods. I tried to implement both of them separately and are working fine. So, What's the difference between these two twins?

onResume():
protected void onResume()
Called after onRestoreInstanceState(Bundle), onRestart(), or onPause(), for your activity to start interacting with the user. This is an indicator that the activity became active and ready to receive input. It is on top of an activity stack and visible to user.
On platform versions prior to Build.VERSION_CODES.Q this is also a good place to try to open exclusive-access devices or to get access to singleton resources. Starting with Build.VERSION_CODES.Q there can be multiple resumed activities in the system simultaneously, so onTopResumedActivityChanged(boolean) should be used for that purpose instead.
Derived classes must call through to the super class's implementation of this method. If they do not, an exception will be thrown.
If you override this method you must call through to the superclass implementation.
 onPostResume():
protected void onPostResume()
Called when activity resume is complete (after onResume() has been called). Applications will generally not implement this method; it is intended for system classes to do final setup after application resume code has run.
Derived classes must call through to the super class's implementation of this method. If they do not, an exception will be thrown.
If you override this method you must call through to the superclass implementation.

onPostResume :
Called when activity resume is complete (after activity's {#link #onResume} has been called). Applications will generally not implement this method; it is intended for system classes to do final setup after application resume code has run.
It will do following things
It will ensure that screen is visible to user and will do the final set up for activity.
Remove any pending posts of messages with code 'what' that are in the message queue.
Check all fragment gets resumed and Moves all Fragments managed by the controller's FragmentManager into the resume state.
Execute any pending actions for the Fragments managed by the controller's FragmentManager.
If you check it life cycle vise it worked like below
onResume() - Activity
onResume() - Fragment check third point as explained above
onPostResume() - Activity
See here please: Activity life cycle methods : onPostResume significance

Related

Android show dialog causes illegal state exception if activity recreated

There are three activities: Login, Main and Profile
Obviously from Login you can go to Main. There is a Button that calls AppCompatDialogFragment in Main.
BalanceCalculationDialog dialog = BalanceCalculationDialog.newInstance(model);
dialog.setListener(this);
dialog.show(getSupportFragmentManager(), "TAG");
If I user enters Main for the first time dialog shows.
If user goes to Profile and then backs dialog shows.
If user goes out from Main (finish() with Intent#FLAG_ACTIVITY_NEW_TASK and Intent#FLAG_ACTIVITY_CLEAR_TASK flags) and tries to see dialog he sees an error.
java.lang.IllegalStateException: Can not perform this action after
onSaveInstanceState....CheckStateLoss()...
As far as I know it caused because "Transaction cannot be commited after onSaveInstanceState()".
I tried to override this method leaving empty body, not calling super and didn't work.
Then I found another way to solve problem, which worked:
#Override
public void show(FragmentManager manager, String tag) {
try {
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commitAllowingStateLoss();
} catch (IllegalStateException e) {
Log.e("ILLEGAL", "Exception", e);
}
}
Nevertheless I don't understand why it works this way -> Number of catching IllegalStateException equals the number of recreating Main. For example I log out 20 times - then I will have 20 catching of mentioned exception. So I don't find this solution as the right one.
In addition, I have other activities that can call another dialogs. These activities also can be finished with finish() and when user opens one of them again he doesn't have the issue.
I would be very glad to have proper explanation of such behaviour and right way of solving it. Thank you very much.
EDIT
Reason of this issue was usage of RxJava EventBus. When I switched to Otto Eventbus problem disappeared. RxJava allows you to send and get messages without subscribe and unsubscribe that can cause unexpected behaviour.
The exception was thrown because you attempted to commit a FragmentTransaction after the activity’s state had been saved, resulting in a phenomenon known as Activity state loss. Before we get into the details of what this actually means, however, let’s first take a look at what happens under-the-hood when onSaveInstanceState() is called. Android applications have very little control over their destiny within the Android runtime environment. The Android system has the power to terminate processes at any time to free up memory, and background activities may be killed with little to no warning as a result. To ensure that this sometimes erratic behavior remains hidden from the user, the framework gives each Activity a chance to save its state by calling its onSaveInstanceState() method before making the Activity vulnerable to destruction. When the saved state is later restored, the user will be given the perception that they are seamlessly switching between foreground and background activities, regardless of whether or not the Activity had been killed by the system.
When the framework calls onSaveInstanceState(), it passes the method a Bundle object for the Activity to use to save its state, and the Activity records in it the state of its dialogs, fragments, and views. When the method returns, the system parcels the Bundle object across a Binder interface to the System Server process, where it is safely stored away. When the system later decides to recreate the Activity, it sends this same Bundle object back to the application, for it to use to restore the Activity’s old state.
So why then is the exception thrown? Well, the problem stems from the fact that these Bundle objects represent a snapshot of an Activity at the moment onSaveInstanceState() was called, and nothing more. That means when you call FragmentTransaction#commit() after onSaveInstanceState() is called, the transaction won’t be remembered because it was never recorded as part of the Activity’s state in the first place. From the user’s point of view, the transaction will appear to be lost, resulting in accidental UI state loss. In order to protect the user experience, Android avoids state loss at all costs, and simply throws an IllegalStateException whenever it occurs.
Solution for this exception is
Be careful when committing transactions inside Activity lifecycle methods. A large majority of applications will only ever commit transactions the very first time onCreate() is called and/or in response to user input, and will never face any problems as a result. However, as your transactions begin to venture out into the other Activity lifecycle methods, such as onActivityResult(), onStart(), and onResume(), things can get a little tricky. For example, you should not commit transactions inside the FragmentActivity#onResume() method, as there are some cases in which the method can be called before the activity’s state has been restored (see the documentation for more information). If your application requires committing a transaction in an Activity lifecycle method other than onCreate(), do it in either FragmentActivity#onResumeFragments() or Activity#onPostResume(). These two methods are guaranteed to be called after the Activity has been restored to its original state, and therefore avoid the possibility of state loss all together. (As an example of how this can be done, check out my answer to this StackOverflow question for some ideas on how to commit FragmentTransactions in response to calls made to the Activity#onActivityResult() method).
Avoid performing transactions inside asynchronous callback methods. This includes commonly used methods such as AsyncTask#onPostExecute() and LoaderManager.LoaderCallbacks#onLoadFinished(). The problem with performing transactions in these methods is that they have no knowledge of the current state of the Activity lifecycle when they are called. For example, consider the following sequence of events:
An activity executes an AsyncTask.
The user presses the “Home” key, causing the activity’s
onSaveInstanceState() and onStop() methods to be called.
The AsyncTask completes and onPostExecute() is called, unaware that the
Activity has since been stopped. A FragmentTransaction is committed
inside the onPostExecute() method, causing an exception to be thrown.
In general, the best way to avoid the exception in these cases is to
simply avoid committing transactions in asynchronous callback methods
all together.
Use commitAllowingStateLoss() only as a last resort. The only difference between calling commit() and commitAllowingStateLoss() is that the latter will not throw an exception if state loss occurs. Usually you don’t want to use this method because it implies that there is a possibility that state loss could happen. The better solution, of course, is to write your application so that commit() is guaranteed to be called before the activity’s state has been saved, as this will result in a better user experience. Unless the possibility of state loss can’t be avoided, commitAllowingStateLoss() should not be used.
But I have to agree that this is an Android framework design defect. Google devs try to fix it over many version. But seems like there is no good approach to work-around this. Just understand the life cycle and remember to check the state of activity carefully before committing transaction

Is the method onSaveInstanceState(Bundle) called after onPause()?

I'm new to android and I read a book for beginners which said that onSaveInstanceState(Bundle) is ensured to be called before the system reclaims your Activity.
I tried it on some test codes and found it incorrect. I found that onSaveInstanceState(Bundle) was called every time after onPause() was called. And it has nothing to do with system reclaimation.
I'm not very sure about it, so that's the question: when is onSaveInstanceState(Bundle) called actually?
I don't agree with a previous answer.
According to the Documentation:
If called, this method will occur before onStop(). There are no
guarantees about whether it will occur before or after onPause().
According to Android Documentation:
In addition, the method onSaveInstanceState(Bundle) is called before placing the activity in such a background state, allowing you to save away any dynamic instance state in your activity into the given Bundle, to be later received in onCreate(Bundle) if the activity needs to be re-created. See the Process Lifecycle section for more information on how the lifecycle of a process is tied to the activities it is hosting. Note that it is important to save persistent data in onPause() instead of onSaveInstanceState(Bundle) because the latter is not part of the lifecycle callbacks, so will not be called in every situation as described in its documentation.
Yes onPause() is called before onSaveInstanceState(Bundle). But onPause() is guaranteed to be called as its a part of activity life cycle
Usually when your activity is re-created for example when you change device orientation then onSaveInstanceState(Bundle) is called if you have not specified the android:configChanges tag in your manifest.xml file.

What is the best equivalent of a main() function for an Android app?

I've searched everywhere a manner to have the equivalent of a main() function (yes function not method) inside a Android application but failed...
Typically what I would want to do is:
void main()
{
// do some really nice initialisations stuff here
// ... let the app does his life, I really don't care
// do some final stuff here before leaving
}
The nearest approach I've seen so far is to use a SplashScreen and override the OnCreate() method. The problem is that is not acceptable from my point of view.
Why? Because a SplashScreen is nothing than an Activity tagged as a LAUNCHER.
That makes it to appear in the apps list, thing I don't want when I develop an app widget.
Furthermore, where to place my code just before the app destroy? In the onDestroy() method?
No, once again, this is not reliable. Android can decide to delete my instance whereas the application is still running.
Well, in fact, I take for principle that every components of my app are running in the same process since I don't mention explicitely in the Manifest that I wan't a component to run in its own process.
In the case of an app widget, I've placed my init code on the first call of onUpdate() method. I think it's a good bet. Then this app widget (AppWidgetProvider more precisely) is in charge to launch any activity as its will.
The "DataBase" for all the app is defined in a separate Singleton like this:
public class MyDataBase {
public static MyDataBase getInstance() {
if (instance_ == null)
instance_ = new DataBase();
return instance_;
}
public void load();
public void save();
static MyDataBase instance_ = null;
public int myInt;
public String myString;
public Object myObject;
etc..
}
With this Singleton I'm sure at least, its lifecycle is the same as the entire app itself.
To back with that AppWidgetProvider, I have to trick a little. Indeed, Android can decide to delete its instance whereas some other activities are still on place and the process is still running. So for example, systematically loading my DataBase in the first call of the OnUpdate() is unnecessary and overkill. What I do is having a static boolean value that indicates if the DataBase have been loaded for the lifecycle of this process or not.
Thus, the AppWidgetProvider can be instanciated tons of time, as long as the Singleton DataBase persists (so the process), it will not reload the DataBase each time, got it?
(yes difficult to be clear...)
About the cleanup code of the app, I thought to override the finalize() method of my DataBase Singleton, but well, I'm really not sure it's a good idea since the moment of the call of this method is totally unpredictable. I suppose it would be called if you suddently power off your Android, but well I'm not sure of anything here, thus so far, I didn't found a solution for that part.
Any comment or something less tricky that what I currently do is welcome.
Thanks.
onResume() is the function that will be invariably reached before starting you app, so you could either put the 'main' code in the onCreate() method or the onResume().
onPause() is ALWAYS called before destroying the app, either by the user or the OS.
There is great explanation regarding the lifecycle in the Android documentation:
http://developer.android.com/training/basics/activity-lifecycle/starting.html
For the initialisation you can over-ride the onCreate method of the Application class:
Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created. Implementations should be as quick as possible (for example using lazy initialization of state) since the time spent in this function directly impacts the performance of starting the first activity, service, or receiver in a process. If you override this method, be sure to call super.onCreate()
Termination is harder to deal with. You'll probably have to monitor each component of your application separately. If you are targeting API level 14 or later you can use Application.registerActivityLifecycleCallbacks to help with this.
The nearest approach I've seen so far is to use a SplashScreen and
override the OnCreate() method. The problem is that is not acceptable
from my point of view. Why? Because a SplashScreen is nothing than an
Activity tagged as a LAUNCHER.
It's because Android is formed with several activities and those activities have life cycles. So every activities start from onCreate() then finishes at onDestroy().
http://developer.android.com/training/basics/activity-lifecycle/starting.html
That makes it to appear in the apps list, thing I don't want when I
develop an app widget. Furthermore, where to place my code just before
the app destroy? In the onDestroy() method? No, once again, this is
not reliable. Android can decide to delete my instance whereas the
application is still running.
In a scenario that user presses home button to exit from your app, your current activity is more likely to invoke onPause() method (only when the activity has no other processes to finish). However, when user force closes (terminates) your whole application by ending process. Then you don't have to worry about invoking any methods or what so ever because Android itself will close anything related to your application automatically.
To back with that AppWidgetProvider, I have to trick a little. Indeed,
Android can decide to delete its instance whereas some other
activities are still on place and the process is still running. So for
example, systematically loading my DataBase in the first call of the
OnUpdate() is unnecessary and overkill. What I do is having a static
boolean value that indicates if the DataBase have been loaded for the
lifecycle of this process or not. Thus, the AppWidgetProvider can be
instanciated tons of time, as long as the Singleton DataBase persists
(so the process), it will not reload the DataBase each time, got it?
(yes difficult to be clear...)
The example you have posted for singleton database connection is not bad I think, but there are better ways to get the job done cleanly and more effectively. For example hibernate framework connection pooling

Android: overriding onPause and onResume - proper way

When overriding the onPause() and the onResume() methods of the activity, where is the proper location to call the super.onPause() and super.onResume()? At the beginning of the method or at the end?
From http://developer.android.com/guide/components/activities.html#ImplementingLifecycleCallbacks:
Your implementation of these lifecycle methods must always call the superclass implementation before doing any work, as shown in the examples above.
So, for lifecycle callbacks, like onPause() and onResume(), we should do super.onPause() or super.onResume() at the very beginning. For other methods, it all depends on the semantics of the super class.
Update: This is the accepted answer and it contains a nice amount of good information, including a useful diagram, pulled together into one place. However, it appears to be incorrect, at least according to the current Android documentation which, as the poster points out, is the ultimate source for information on the SDK. Possibly the documentation was clarified after this answer was posted. But, in any case, don't stop reading with this answer, check out espinchi's answer below. It has the documentation on its side.
Placement of the super methods depends only on your preference. It would only matter if those methods were taking parameters OR if you were doing some concurrent work. For example if you do this:
#Override
protected void onPause() {
try {
someOtherThread.join();
} catch (InterruptedException e) {
LOG.e(e);
}
super.onPause();
}
it might block the thread and prevent super from being called.
I suggest that you should read all documentation available because they will help you much. For example this is what you can find in the onPause javadoc. I bolded out the important parts:
Called as part of the activity lifecycle when an activity is going
into the background, but has not (yet) been killed. The counterpart to
onResume().
When activity B is launched in front of activity A, this callback will
be invoked on A. B will not be created until A's onPause() returns, so
be sure to not do anything lengthy here.
This callback is mostly used for saving any persistent state the
activity is editing, to present a "edit in place" model to the user
and making sure nothing is lost if there are not enough resources to
start the new activity without first killing this one. This is also a
good place to do things like stop animations and other things that
consume a noticeable amount of CPU in order to make the switch to the
next activity as fast as possible, or to close resources that are
exclusive access such as the camera.
In situations where the system needs more memory it may kill paused
processes to reclaim resources. Because of this, you should be sure
that all of your state is saved by the time you return from this
function. In general onSaveInstanceState(Bundle) is used to save
per-instance state in the activity and this method is used to store
global persistent data (in content providers, files, etc.)
After receiving this call you will usually receive a following call to
onStop() (after the next activity has been resumed and displayed),
however in some cases there will be a direct call back to onResume()
without going through the stopped state.
Derived classes must call through to the super class's implementation
of this method. If they do not, an exception will be thrown.
I do recommend this flowchart for you it will help your development tremendously:
It probably doesn't matter, but to know for sure, you need to know what the super methods are doing, and usually that information is not available to you.
My style is to call e.g. super.onCreate(), super.onResume(), etc. before the body of my own method, and e.g. super.onPause() and super.onDestroy() after the body of my own method.
The theory behind this is that I like to let the super methods run first while building something up, just in case what I'm doing depends on what the superclass sets up first, and when tearing something down, I like to tear down my own stuff before the superclass tears down its stuff.
There's no right or wrong.
That depends on what you do on your implementation of these methods.
Sometimes you'll want the super to be before your code, and sometime after.
You can put it anywhere. First you have to understand the Activity life cycle. Check the following link Here
Download the demo and run it you will be clear
Delving into the android code, you can find that the framework sets a flag called mcalled when you call super.onPause(). This flag is later checked on resume by the framework.
if (!mCalled) {
throw new SuperNotCalledException(
"Activity " + mComponent.toShortString() +
" did not call through to super.onResume()");
}
All you need to do is make sure the call is made to super and you are good. No other precaution is necessary.

Android "single top" launch mode and onNewIntent method

I read in the Android documentation that by setting my Activity's launchMode property to singleTop OR by adding the FLAG_ACTIVITY_SINGLE_TOP flag to my Intent, that calling startActivity(intent) would reuse a single Activity instance and give me the Intent in the onNewIntent callback. I did both of these things, and onNewIntent never fires and onCreate fires every time. The docs also say that this.getIntent() returns the intent that was first passed to the Activity when it was first created. In onCreate I'm calling getIntent and I'm getting a new one every time (I'm creating the intent object in another activity and adding an extra to it...this extra should be the same every time if it was returning me the same intent object). All this leads me to believe that my activity is not acting like a "single top", and I don't understand why.
To add some background in case I'm simply missing a required step, here's my Activity declaration in the manifest and the code I'm using to launch the activity. The Activity itself doesn't do anything worth mentioning in regards to this:
in AndroidManifest.xml:
<activity
android:name=".ArtistActivity"
android:label="Artist"
android:launchMode="singleTop">
</activity>
in my calling Activity:
Intent i = new Intent();
i.putExtra(EXTRA_KEY_ARTIST, id);
i.setClass(this, ArtistActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
startActivity(i);
Did you check if onDestroy() was called as well? That's probably why onCreate() gets invoked every time instead of onNewIntent(), which would only be called if the activity is already existing.
For example if you leave your activity via the BACK-button it gets destroyed by default. But if you go up higher on the activity stack into other activities and from there call your ArtistActivity.class again it will skip onCreate() and go directly to onNewIntent(), because the activity has already been created and since you defined it as singleTop Android won't create a new instance of it, but take the one that is already lying around.
What I do to see what's going on I implement dummy functions for all the different states of each activity so I always now what's going on:
#Override
public void onDestroy() {
Log.i(TAG, "onDestroy()");
super.onDestroy();
}
Same for onRestart(), onStart(), onResume(), onPause(), onDestroy()
If the above (BACK-button) wasn't your problem, implementing these dummies will at least help you debugging it a bit better.
The accepted answer is not quite correct. If onDestroy() was called previously, then yes, onCreate() would always be called. However, this statement is wrong:
"If you go up higher on the activity stack into other activities and from there call your ArtistActivity.class again it will skip onCreate() and go directly to onNewIntent()"
The "singleTop" section of http://developer.android.com/guide/components/tasks-and-back-stack.html explains plainly how it works (attention to bold text below; I've also proven this through my own debugging):
"For example, suppose a task's back stack consists of root activity A with activities B, C, and D on top (the stack is A-B-C-D; D is on top). An intent arrives for an activity of type D. If D has the default "standard"launch mode, a new instance of the class is launched and the stack becomes A-B-C-D-D. However, if D's launch mode is "singleTop", the existing instance of D receives the intent through onNewIntent(), because it's at the top of the stack—the stack remains A-B-C-D. However, if an intent arrives for an activity of type B, then a new instance of B is added to the stack, even if its launch mode is "singleTop"."
In other words, starting an activity through SINGLE_TOP will only reuse the existing activity if it is already at the top of the stack. It won't work if another activity in that same task is at the top (for example, the activity that is executing startActivity(SINGLE_TOP)); a new instance will be created instead.
Here are two ways to fix this so that you get the SINGLE_TOP behavior that you want -- the general purpose of which is to reuse an existing activity, instead of creating a new one...
First way (as described in the comment section of the accepted
answer): You could add a launchMode of "singleTask" to your Activity. This would force onNewIntent() because singleTask means there can only be ONE instance of a particular activity in a given task. This is a somewhat hacky solution though because if your app needs multiple instances of that activity in a particular situation (like I do for my project), you're screwed.
Second way (better):
Instead of FLAG_ACTIVITY_SINGLE_TOP, use FLAG_ACTIVITY_REORDER_TO_FRONT. This will reuse the existing activity instance by moving it to the top of the stack (onNewIntent() will be called as expected).
The main purpose of FLAG_ACTIVITY_SINGLE_TOP is to prevent the creation of multiple instances of an Activity. For instance, when that activity can be launched via an intent that comes from outside of your application's main task. For internal switching between activities in my app, I've found that FLAG_ACTIVITY_REORDER_TO_FRONT is generally what I want instead.
Set this flag to your intent:
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP)

Categories

Resources