There's a scenario in my app which it could go activity a->activity b->activity a->activity b...infinitely, and eventually it'll get OOM.
Is anybody aware of a way to make it like the "don't keep activities" behaviour,e.g. the activities will be killed to release memory but still in history, so it can be recreated as user navigates back?
This isn't possible. The activities need to be present in the stack for Android to be able to go back to them. What you can do is to keep track of the data that the activities are managing yourself, so that as the user goes from ActivityA to ActivityB to ActivityA you keep pushing a data packet onto a stack that is available to both activities. Then you can use `Intent.FLAG_ACTIVITY_REORDER_TO_FRONT' to transition from one activity to the next.
In this case you will only ever have one instance of ActivityA and one instance of ActivityB, but they should be able to present the user a different view each time they get control by just looking at the data packet on the top of the stack. When the user presses the back button, you should pop the top data packet off the stack and then start the appropriate activity for it (using `Intent.FLAG_ACTIVITY_REORDER_TO_FRONT' to ensure that you don't create a new instance).
Related
I wrote a small game on android. It has one activity + one fragment. I save the state of the game in Fragment.onSaveInstanceState and restore the state in Fragment.onCreateView.
If I rotate the screen, the game state is preserved properly. However, if I turn off the screen and come back to the game at a later time, sometimes I lose the game state and get a new game instead. Therefore, I wonder if Fragment.onSaveInstanceState is called at all when the system decides to kill a process to recover memory. Also, what is the life time of the stuff that gets saved into the Bundle in Fragment.onSaveInstanceState?
By the way, is there anyway to easily test such a case during development? It'd be terribly inefficient to wait for a day or two for the system to kill it.
Thanks for helping me out!
I wonder if Fragment.onSaveInstanceState is called at all when the system decides to kill a process
Yes.It is called.
I think your issue lies somewhere here.From the documents :
The most significant difference in lifecycle between an activity and a
fragment is how one is stored in its respective back stack. An
activity is placed into a back stack of activities that's managed by
the system when it's stopped, by default (so that the user can
navigate back to it with the Back button, as discussed in Tasks and
Back Stack). However, a fragment is placed into a back stack managed
by the host activity only when you explicitly request that the
instance be saved by calling addToBackStack() during a transaction
that removes the fragment.
Not sure if this can solve your problem but i think you should keep it in mind while writing your game code.
I have an app, a single activity app with fragments in it.
The usual use case for this app is, that you start it and put the phone away and every now and then, you get back to the phone and insert some data... It's a logging app, you are doing something and insert your results into the app...
I have the problem, that every now and then, my activity get's destroyed and is recreated with an empty bundle... (Most of the time this is not the case, but every now and then this happens...). My app sometimes starts a service, even this service is killed in this case...
This means, that the system has killed my app, does it? How can I avoid this?
I need to keep the user data and the current top fragments... And they are saved to the bundle and everything works as long as their states and the data get saved...
Btw., my activity is always the TOP ACTIVITY, only that the screen turns off often... I just want to keep my activity alive as long as possible until the user leaves it with the back button... Or to save the state reliably
IMPORTANT NOTE
onSaveInstance does not always work (it's not part of the lifecycle and therefore not guaranteed to be called)... it only works most of the time... I need a way to that works always... If android kills my app...
don't keep your app in memory
You don't want to block Android from killing your app. What you want is to restore your app's state properly. Then the user will never notice the app has been destroyed and the user still gets the benefit of an app that was destroyed when not in use.
If you really want this use a wakelock. This will drain your users battery so I think twice before implementing this... Info at How do I prevent an Android device from going to sleep programmatically?
onSaveInstanceState explained
To do so check what information is needed in the bundle and persist that information with the onSaveInstanceState(bundle:Bundle) method so you can reuse it in onCreate(sameBundle:Bundle).
More information available from Google documentation at Save your Activity state and Restore your Activity State.
About Android Activity lifecycle
As stated by #prom85 in the comments below it's not guaranteed that the onSaveInstanceState method will be called because it's not part of the lifecycle. Workaround for this is using the onPause lifecycle hook to ensure your data is stored.
More information at Android: onSaveInstanceState not being called from activity
I had a similar problem, I arrived at this post while searching for a solution, you have to play with the manifest to achieve this and also understand what exactly activity is, in Android eco system,
In Android activity is a task which has a pre defined work.
I dig a lot in the documentation, I found that, we can configure activity in two ways,
Persistent
non persistent
if you mention for the activity in the manifest as
android:persistent="true"
and run the below use case
Start the APP
Press back or home button
you select the activity in the back stack again to bring it to front
Activity enters start -> pause -> stop - > resume , it does not get into onDestroy method.
if do not mention
android:persistent="true"
for the same use case
Activity enters start -> pause -> stop -> destroy, and if you select the activity from the back stack
Activity enters resume->create->start
If you want to run a service/task on activity start which keeps running when the app is in back stack, then you have to start that in the onCreate method, and kill them onDestroy by specifying your activity as persistent in manifest.
I hope my above solution might help others who arrive here for the same problem
Most of my activities load dynamic data from a server, and when the page comes back into focus, i reload it anyway. It seems wasteful to keep them around if I'm just going to reload them, so I thought of calling finish() on them if the user navigates away from the page.
Its confusing if some activities you can press the back button to go to and others no because I've called finish() on them, so I was wondering if its bad practice just to call finish() on all activities the user navigates away from? (I have a navigation bar at the bottom of every activity so the back button isnt necessary). Or, is it better practice not to call finish() on any of the activities and just hope they dont slow down the phone and that the OS will take care of garbage collecting them?
I'm new to Android programming and and don't have an Android phone so i'm not sure what is the common/best practice in this situation, or if its just a matter of personal taste.
Also, is it possible to instruct Android to keep a history of activities so that the back button still works, but finish() them when they navigate away so that they're not needlessly taking up resources?
While you may reload all your data on returning to the activity, there is still no point on calling finish().
When activities are hidden, they do not use resources, and are of no real problem. Just leave them as is, and then when the user navigates back, it will reload it as required.
In this state, they can also be garbage collected if required - which is all taken care of by android.
In most circumstances you do not need to (and should not) call finish(); Android takes care of managing the activities for you.
If you need to do cleanup when a user leaves the activity, you can do that sort of thing in the various activity callbacks such as onDestroy().
If you haven't done so already, read Activities in the Android developer guide.
You shouldn't call finish() unless you're sure that activity won't be executed in a long time. It's better to let Android handle what to do with it. Put your cleaning code in onPause() and your loading code in onResume().
I am developing a game for Android and have what I imagine to be a very common scenario, but I can't figure out how to do it.
I have a Title Screen where the user can select "New Game". When they start up a game, I push a GameActivity onto the stack. Then if the user hits the physical back button the phone, the application goes back to the TitleActivity, as I intend it. However, I need a way to allow the user to resume the game at this point, but I don't know how to get back to htat instance of the GameActivity. Any help is appreciated.
You can't guarantee that you will get back to that instance of GameActivity you need to save the game state somehow, and make your GameActivity able to resume from that saved state.
Make sure you understand the Activity lifecycle. The instance of your activity can be killed at any time when it isn't visible, so you need to save state at the proper point (onSaveInstanceState).
The answer I would give is: don't do this.
Finishing an activity (which is what happens by default when you press back) does finish that activity. You don't return to it.
If you want to allow the user to press back to pause your game into a menu, capture the back key with onBackPressed(), and instead of allowing the default behavior of finishing the activity, simply show your menu in-place in that activity. Generally I think for games making the core game UI be one activity that is the base activity launched for the app makes more sense than trying to split it into activities. Games are just special that way.
I'm not talking about restoring application state (using Bundle or configuration change or even SharedPreferences) i'm talking about the fact that i have a certain task, that is a base activity: HomeScreenActivity and from there i can have a series of activities opened for the user's flow.
I want in case of application's death or user killed his own session to restore the whole task, not just one activity, i mean to restore the whole activity stack i had before the application was killed. if the user was in my billing screen and left off my app i want to take him back to that screen, but i want that if he'll press back he'll go back to my search screen or filtering screen, whatever was there before he left off.
I have no problem saving the activity's order in sharedPreferences and know the order once i start my home screen, but i wonder if there's a way to tel landroid to start an activity, which sould only enter the task's stack and not call the activity's onCreate method unless i actually get to it(with back key).
Perhaps someone will have a better idea, but the only thing that comes immediately to mind is to add a "resetup" flag so that you could sort of replay a script of the user's previous activity navigation actions within your app, having your activities start each other up in turn but due to the resetup flag bypassing most of their code so they don't really do anything except essential setup and start the next one.
One complication is that it's probably the activity they were actually in which android will resume.