Fragment being destroyed when host activity resumes - android

I'm working on an Android app and have noticed that after pausing and resuming the app (e.g. going to Home page or another app then returning to the original app), I am losing information from the fragment in between the pause and resume. On debugging I found that when I resume the app the fragment is being destroyed by FragmentManager during the host activity's onResume. (There is no code in the host activity's onResume which explicitly destroys the fragment.)
When I try and reproduce this in a simple app, it doesn't happen.
I can't see anything in the Android Lifecycle documentation which says the fragment gets destroyed when the app is resumed.
I'm ploughing through the FragmentManager code to try and work out why this is happening, but I'm wondering, does anyone know of any circumstance when this would happen / could you point me to documentation which explains this?
Let me know if you'd like more information or a link to the code. (I'm not expecting anyone to plough through the code, it's just if you want to get more information.)
Code snippet from host activity:
abstract class MainNavDrawerActivity : AppCompatActivity(), OnNavigationItemSelectedListener, Route.Listener {
...
public override fun onResume() {
...
super.onResume() // (line 190)
...
}
debug stack

Related

Question about lifecycle methods definition

I learning Android about 6 month, and all this time i described Lifecycle methods like some kind of callback, which "trigerred" when OS change state or configuration.
Questions:
1) For example, User rotate the screen. As i think, Android invoce some interface and Activity runing it's code when callback come. I'm not sure about it, because i got throw documentation(Activity/Window/...classes) and i did't find this interface or smth like it. What's really happen when user rotate the screen?
2) For example, user push the button on his mobile app and create new Activity. Lifecycle methods will be called, but OS state or configuration was't change. It means, my definition of lifecycle methods is wrong. How to describe it correctly? Help me to understand what's wrong with my first definition.
I know about this link:
https://developer.android.com/guide/components/activities/activity-lifecycle
And there is a line:
The Activity class provides a number of callbacks that allow the activity to know that a state has changed...
But inside Activity class i see, for example:
#MainThread
#CallSuper
protected void onCreate(#Nullable Bundle savedInstanceState) {
and i have not see override word, so how Activity can implement it?
There is #CallSuper annotation, but parent classes(include Context) have no code connected with lifecycle. So it this real callbacks?
Not sure that I understand your question, because it is vague, but let me try to address the 2 specific examples:
1) For example, User rotate the screen. As i think, Android invoce
some interface and Activity runing it's code when callback come. I'm
not sure about it, because i got throw
documentation(Activity/Window/...classes) and i did't find this
interface or smth like it. What's really happen when user rotate the
screen?
In the usual case, when the user rotates the screen, a "configuration change" occurs. Android responds to this by killing off the currently active Activity. Android calls the "lifecycle methods": onPause(), onStop() and onDestroy() on the current Activity. Android then creates a new instance of the Activity and calls the "lifecycle methods": onCreate(), onStart() and onResume on that instance.
In case the application has declared that it wants to handle the configuration change itself (by specfying android:configChanges="..." for the Activity in the manifest), Android does not kill the Activity when the screen is rotated. Instead, Android calls the "lifecycle method": onConfigurationChanged() on the current Activity.
2) For example, user push the button on his mobile app and create new
Activity. Lifecycle methods will be called, but OS state or
configuration was't change. It means, my definition of lifecycle
methods is wrong. How to describe it correctly? Help me to understand
what's wrong with my first definition.
The "lifecycle methods" do not only refer to changes int he OS state or configuration. "Lifecycle methods" are also called to inform your Activity about changes in the state of the Activity itself. onCreate() is called to inform the Activity that a new instance of the Activity has just been created by Android and that the Activity should initialize itself. onResume() is called to inform the Activity that it is now the current Activity that the user will see (topmost Activity in its task and visible on screen). onPause() is called to inform the Activity that another Activity is going to become the current Activity. onConfigurationChanged() is called to inform the Activity that a configuration change has occured on the device (this can be one of many differnt things including: locale, screen size, screen density, screen orientation, keyboard presence, etc. There are many other "lifecycle methods" that are called by Android at specific times during the lifetime of an Activity.

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 :-)

Understanding Android lifecycle - onDestroy()

I have MainActivity and SecondActivity in my practice app to understand activity lifecycle. I am clicking the overview button closing the app once it is in MainActivity ( see below which does not call its onDestroy())
and closing the app once I navigate to the SecondActivity through a button click(in this case MainActivity's onDestroy() is called, image below)
I am not sure how important understanding this scenario is, as I am preparing for my interviews. Any advise is much appreciated.
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.
so,you can't be always sure, that this method will be called
here is the google docs
https://developer.android.com/reference/android/app/Activity.html#onDestroy%28%29*

Changes to SQLite database lifecycle between Gingerbread and ICS; intermittent null pointer exception

I noticed that after I upgraded to ICS from Gingerbread my app started crashing in circumstances when it had worked satisfactorily under Gingerbread.
The app's main activity (activity A) has a menu option which opens a ListActivity (activity B) populated from a database; when an entry in the list is clicked a third activity (activity C) is opened. When activity C is closed with the Back button activity B is supposed to be redisplayed.
In Gingerbread (and earlier Android versions) this worked fine, and continued to work OK in ICS most of the time. However, it crashed if I navigated away from the app leaving activity C open for an extended period. On returning to the app and trying to back out of activity C to activity B the app would stop. LogCat reported "unable to resume activity" because of a null pointer exception in onResume in activity B.
The offending line in the onResume method contains a reference to a DBAdapter which is defined in the onCreate method of activity A. By logging calls to activity B's various lifecycle methods I found that activity B is always (as expected) stopped when activity C is opened. Provided it is only stopped there is no problem: the DBAdapter must still be defined when onResume is called. However, if the app is left for a longer period activity B is destroyed and in these circumstances the DBAdapter (defined in the onCreate method of activity A) must also become undefined.
A fix for this problem seems to be to insert if (Global.mDBAdapter== null) {Global.mDBAdapter = new DBAdapter( this, "DatabaseName" );} into the onCreate method of activity B.
I would like to check that I have understood this correctly. Is there documentation that describes the change (between Gingerbread and ICS) in lifecycle behaviour of a SQLite database adapters/helpers?
It seems you were making assumptions that weren't warranted, and you just happened to be getting away with them on your Gingerbread device.
An Activity's process is always killable any time after onStop() has been called, so at the end of onStop(), you must be prepared for your next lifecycle callback to be any of these three:
onRestart() -- If the process isn't killed and the Activity is restarted before long.
onDestroy() -- If the system has decided to stop the activity and finds it convenient to let you know.
onCreate() -- If the process was killed without calling onDestroy().
(Pre-Honeycomb, the process is even killable after onPause().)
So what it sounds like is happening is that when you've navigated away from Activity C for a long period, the whole process is killed. When you go back to Activity C, then press BACK, Activity B goes through onCreate() -> onStart() -> onResume(), and you seem to be assuming you have global state set up by Activity A, which isn't the case.
This wasn't a change between Gingerbread and ICS; you were just getting lucky before.
Good resources to read and understand:
The Developer Guide article on Activities
The documentation for Activity
Update: You asked in the comments below what exactly Android retains about your application state when it is destroyed. My impression is that it is basically just the Activity stack and any Bundles from onSaveInstanceState(). (It doesn't specifically remember which Activity was open, that's just the top of the stack.) That makes sense: Android handles its end of things (the Activity stack) and you handle yours (by saving what's most important and being prepared to recreate the rest).
The default implementation of onSaveInstanceState() calls the method of the same name on all of your Views, which can make it seem like you're getting some data saved and restored for free. Without overriding that method, however, you certainly won't have any of your own data members saved, static or otherwise. That makes a lot of sense to me: automatically doing so would require reflection and would be inefficient, often wasteful, and quite confusing. It's up to you to save what's important to be saved, and Android gives you the callbacks to make this easy.
Here's another resource for you:
Recreating an Activity
You don't necessarily need to deal with onSaveInstanceState(), however; some things make much more sense to be recreated, e.g. your database adapter.

Activity.finish() called but activity stays loaded in memory

When I run my app on the debugger, I get the main thread and 3 binder threads.
On a button click I call Activity.finish(), which looks like it ends the activity as the UI closes and goes back to the home screen.
However, in the debugger, it still shows the main thread and 3 binder threads as "(running)".
I am baffled to why this is happening. Even more so, it is causing my app to call Activity.onResume() when I run it again after exiting the app.
I currently override these methods in the Activity, but I call the appropriate super functions in each one:
onDestroy()
onPause()
onResume()
onSaveInstanceState()
Any help or advice regarding this is much appreciated!
You don't control when your app leaves main memory, the OS does. Look closely at Activity.finish...
Call this when your activity is done
and should be closed. The
ActivityResult is propagated back to
whoever launched you via
onActivityResult().
Note that is says nothing about memory. As to calling Activity.onResume, that's exactly what you would expect for the lifecycle; remeber that onResume is not just called after a resume but even when the app is first launched after onCreate.
While not exactly what you asked I suggest you read this article about exit buttons which goes on to say something very important
[Activity.finish] is exactly equivalent to hitting the back button.

Categories

Resources