android memory management in activity lifecycle
My question is a little bit complicated.
I want to understand how the app treats resources (especially images for backgrounds, buttons, etc.) when Activity is started, then suspended.
For example, I start Activity A, it shows all the images on the screen, eats its memory, then another Activity B is started and A is suspended. What happens to all the images, resources, etc.? When they are freed? How can I take control over them? Should I not k开发者_高级运维eep the Activity A in the memory and remove it from the Activity stack?
If you need any clarification for my questions, pls write me!
Thanks in advance! Danail
Activity doesn't free resources until it's finished. But in most cases it mustn't be a problem for you. In my opinion, you shouldn't add your own resource management and make your code complicated in most cases.
But if you really think that your app can be out of memory, you should check it with something like MAT. Problems with memory may be caused by memory leaks, not heavy memory usage.
Eventually, when you're absolutely sure that you have to do something to reduce memory usage, you can do some memory optimization. For example, you can save memory-consuming objects (e.g. large images) to local storage in onStop()
and load them in onStart()
. I think using onPause()
/onResume()
for this purpose is a bad idea, because Activity is partially or even fully visible.
In theory, you can even destroy all your widgets in onStop()
and restore them in onStart()
, but it can make your app too slow. And, of course, in this case state saving must be implemented by you.
Finishing activities may seem to be a good idea, but I think it's not. Firstly it makes your work slower. Secondly you must manage activity stack and state of activities yourself. For example, Activity A starts Activity B. So, Activity B must know what to do when user presses Back button. When user presses back button you should start Activity A and restore its state. But what if user terminates this app. In this case you must initialize Activity A with its default state. So, you have to implement a lot of additional logic.
In conclusion I'll repeat the main idea one more time: don't optimize memory usage if you aren't absolutely sure you have to!
Okay so we have the following situation:
A > onCreate
A > onStart
A > onResume
A > Use up a load of memory (A could even use up too much and crash)
A > Launch activity B
B > onCreate
A > onPause
B > onStart
A > onStop
B > onResume
B > Use up a load of memory
If B uses up enough memory then the Android system will kill activity A (you'll notice the onPause and onStop methods of A have already been called so it's already been given a chance to save it's state)
If you then press the back button the Android system will just start activity A again (and if it's clever it should remember it's last state) so it looks like nothing ever happened to the user.
So to be a bit clearer: if you start B and then finish A, B will essentially just replace A in the activity stack and pressing the Back button in activity B will just exit your and app and not return to activity A.
If on the other hand you start B without finishing A, then pressing the back button in B will take you back to A. While activity A is in the background it could be killed to reclaim memory, but Android will recreate it as needed when the user navigates through the activities stack.
Also if you have in memory-caches of multiple objects (e.g. bitmaps/drawables) then back your collection by SoftReferences so that the GC can clear them up if it's running low on memory.
You should design your app so that it's memory usage is low, but you can count on the framework do it's best in memory management. So, do not work too hard with removing unused stuff, only in cases when it's obvious that your app is eating too much memory.
When the available memory goes down, the framework will stop and remove activities and services which are not associated with the current task. If your app eats up even more memory, the framework will stop your activities which are in the background. Then comes the services associated with your app and the last one to finish off will be the current activity.
When the framework stops an activity it does keep record of the activity stack, the intents used for starting the activity and the bundle returned by onSaveInstanceState(), so it can recreate the last known state of the activities. Also, the framework can unload unused resources (drawables, etc.) when not in use and reload them when needed.
Well before replying to your questions, I have certain facts to discuss.
As per the life cycle of the Activity, if we call
finish()
then theonStop()
called and finally theonDestroy()
which eligibles that Activity for Garbage Collection and remove from the Activity Stack of Android.Android is maintaining the Drawable cache for the Activity designing and displaying on the screen. So if you disable the drawable cache on the Activity
onCreate()
.
So the best practice is to disable drawable cache on the onCreate
like this:
LinearLayout v = (LinearLayout) findViewById(R.id.mainLayout);
v.setDrawingCacheEnabled(false);
and to call finish();
on the onPause()
;
You have very little control over memory when you writing Java code. This is a good thing for most of the cases. Actually most of the application do not need to worry about memory.
To answer your question, all the object for activity A will still be in memory when it is suspended. VM will start GC when it needs resource.
精彩评论