My applications memory consumption seems rather high when switching between activities. I quick explanation is that I have an ActivityA that is singleTop and is basically the home screen, you select an item in a list and it takes you to ActivityB which is a more detailed version of the list item. You then press back and it finishes the activity returning to ActivityA. Both activities are quite rich in controls and have high quality images scattered around, but there's definitely something not right here.
I have drawn a quick diagram to show the lifecycle:
As you can see when the app first starts it is at 34MB, after selecting a list item it goes up 2.5MB, then when I press back it goes up again.. this will continue to happen whilst going back and forth. The first thing I need to establish is whether or not this is normal behavior for an application? If this is not the case I clearly have some work to do in releasing some resources, the issue is, what?
In my onDestroy() of ActivityB I unregister from all my receivers, I call finish() on anything I use and have even tried setting everything to null but still no change! I use no special flags when starting ActivityB or finishing it, could that be part of the problem? The history of the stack is sticking around maybe?
EDIT:
I use SceneTransitionAnimation to move an image between the two activities, when I turn this off it goes up 0.5MB each time I go from A to B and 0.01MB when I go from B to A. I guess I should ask the question of how the much bigger increase can be avoided whilst still using SceneTransitionAnimations??
Related
How to switch between screens?
I looked and attempted the above code, and while it does work, it's not what I'm looking for.
In the above example, you open one intent, and then close it when you're done with it. Another example from above showed that I could create new intents endlessly, but then clicking on the Back button of the Android Device makes me go back once for each new intent created, implying that it's going to eat up memory this way.
What I would like to attempt to do is to move between instances of Intents. There will be times when the screens could allow for an endless, memory eating circle of moving between screens.
For example, Screen1 has a button leading to Screen2. Screen2 can lead back to Screen1, or to Screen3. Screen3 can then go back, or go straight back to Screen1. Is there any way to avoid the memory leak for a large number of screens/screen changing/drilling down(Screen1 eventually leading to Screen12 or something)?
In your situation, i suggest you to use a ViewPager to navigate/switch between your Screens.
Just create a Fragment for each Screen (or recycle an old fragment, it depends on what your screens looks like).
Through testing, I was fairly confident that clicking the launcher icon always took the user back to where they left off. However, I loaded my app after keeping it in the background for a long time and found myself on the home screen. When I pressed back, I was taken to the screen I had expected to return to. Things then got messy a I navigated up the activity backstack and found multiple instances of multiple screens. Did this happen because the "current" activity was destroyed by Android? If so, how do I handle that?
My activity hierarchy is similar to League > Division > Team > Player > Injury, so everything but Injury is a parent. I always want the user to be able to resume from any activity. Maybe I should use launchMode="singleInstance"? Should I use it on all activities?
In summary,
I currently declare launchMode="singleTop" for every activity that is a parent, as this initially seemed to cause the user to enter from where they left off.
How should I be handling my activities so that there is never more than one instance and so that the user always enters where they left off?
Try using sharedpreferences and check if it has value then go to a certain main-page.
I have an activity where the user can progress from one fragment to another. The fragment starts, downloads some data and displays it (along with drawing some icons from resources, etc). The user can continue moving forward through fragments for as long as they like (until they get bored?).
The problem is, an OutOfMemoryError will eventually happen (after around 90 fragments on a 32mb vm heap). 90 does seem like quite a lot, but I have seen such memory error reports in the field, so probably this happens earlier on lower-end devices.
I have made sure any views I create in onCreateView I nullify in onDestroyView. The only other objects my fragments hold (as far as I can tell) are the data it downloads at the start, usually only 10-50kb.
My first question is, is this normal? Can I expect to 'only' be able to have ~90 fragments in the back stack? Or do I have a memory leak somewhere that I can do something about?
If the user goes away from my app, and Android decides to kill the whole process to free memory, when the user returns the memory used is much less because the whole state has been restored from bundles. If the user then back-presss through the back stack, each fragment is then of course created/resumed from savedinstancestate.
So my second question is, is there a way to force this to occur? Ie, 'if there are >50 fragments in the back stack, start killing the ones at the bottom to savedInstanceState?'
All back stack Fragment are kept in memory with hard references. So if you are keeping a ridiculous amount of Fragments in back stack then you will get out of memory.
Have a look here: When a Fragment is replaced and put in the back stack (or removed) does it stay in memory?
Try this in your AndroidManifest.xml in <Application> tag:
android:largeHeap="true"
and provide your code to help more.
A fairly common model for iOS apps seems to have a single UITabBarController, where each tab essentially holds a UINavigationController, i.e. a stack of controllers, and pressing a tab switches to the top of the corresponding stack. Can I get the same behavior on Android without a lot of custom code? (Note: I am using menus instead of tabs on Android).
After reading http://developer.android.com/guide/topics/fundamentals/tasks-and-back-stack.html the closest I can see is to have multiple tasks, each one representing a stack (akin to UINavigationController), and to use FLAG_ACTIVITY_NEW_TASK to switch to another task/stack. When I switch, is there a way to go straight to the top of the stack, or do I need to keep that piece of state myself?
One problem with keeping that state myself: I've noticed that if my app launches an Intent that starts a new process, sometimes my original app's process is killed (I think), and all of my global state is destroyed.
The only other solution I can imagine is to have a dummy Activity per stack, to push DummyActivityN essentially right before I switch away from the Nth stack, and, when switching to the Mth stack, to start activity DummyActivityM with FLAG_ACTIVITY_NEW_TASK, and then have DummyActivityM immediately finish() itself.
One last problem: as I navigate to the bottom of one of the stacks, with the back button, I would like to hit the back button once more and NOT go to another stack/task. But this seems easy to overcome by launching an Intent to go to the home screen; is there anything better?
If I understood your problem correctly, if you add this parameter to your Activity declarations in AndroidManifest.xml, the Activities that are launched by your custom menu will be only created once - keeping their state while you move around the tabs.
android:launchMode="singleTask"
I hope this helps,
Best,
-sekran
I have a back button that will work exactly like that.
I know using back button is not a good android practice since android device have one. But my situation badly need it.
I cannot finish my activity and its tough to Keep track of the activity stack.
Since you know that overriding BACK button function is not a good practice, just follow it. Tracking activity stack and promising the BACK behavior can be solved by properly setting the launch mode of each Activity. (please see: Launch Mode in Android Official Site)
If you insist to do something like pressing the BACK button, it's super.onBackPressed().
its better for you to user super.onBackPressed()
Refer Go back to previous activity
I wonder why you wouldn't want to finish your activity. Could you move whatever it is in your activity you don't want to destroy into another object?
BTW: the activity will also be destroyed and re created if the screen is rotated.