First I'm using API 10.
I have activity A and activity B.
I launch activity B from A. Then I call finish() in the oncreate() of B. I then launch activity B from A again and so on. When i do this my native heap keeps increasing by about .5 MB every time.
This is the only code I have in activity B.
super.onCreate(savedInstanceState);
getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
logHeap(); //keeps track of native heap size
setContentView(R.layout.gameplay);
finish();
return;
Are the bitmaps in layout not getting recycled? I don't understand why my native heap size would keep increasing.
You should make sure you're calling bitmap.recycle() when you no longer need the Bitmap. It may take some time for the Bitmap to be recycled by GC.
Found most of it.
Apparently creating from assets
Typeface tf = Typeface.createFromAsset(getAssets(),"fonts/Capture_it.ttf");
isn't garbage collected.
Removing it seemed to fix most of the problem.
Not exactly an answer, but a way to get an answer. If you use MAT (http://www.eclipse.org/mat/) in Eclipse and debug your app, you might find out what exactly is causing the growth in your app's native heap use.
Additionally: from Eclipse, if you access the DDMS, you might be able to use the techniques described here to view which objects are growing.
Related
I have an activity that uses recyclerView and for each item's view there is an Image.
I have used Garbage Collector GC() on Destroy as follows
recyclerView= null;
adapter=null;
Runtime.getRuntime().gc();
But the following thing happens while releasing memory
And When I start another activity that loads images from a remote host using Picasso It says
java.lang.OutOfMemoryError: Failed to allocate a 94784012 byte allocation with 4194304 free bytes and 87MB until OOM
I found an answer that works for me to overcome that OutOfMemoryError
by Increasing heap size for application But I still want to release and ensure that memory occupied by an Activity is released instead of going to increase heap size for app.Thanks in advance , please help to do that task.
The code that you are using in your onDestroy method is not needed there. If destroy is called your acitivity will be removed from the stack and is free for gc anyway with all the resources in it that are only referenced by the activity.
OnDestroy doesn't always get called that's why your method may not be called at all. You could try and explicitly call for finish() in activity then onDestroy will be called and see how the situation will change.But then the activity will be removed from stack.
Also to call for gc manually is supposed to be bad style. On Android the system nearly always knows when it is the best time to do a garbage collection. Most of the times an activity finishes garbage collection is triggered automatically.
I would look into resizing images you get from Picasso first as they just could be too big in general for you heap even if there is space.
Look into resizing options link
Seems the problem is related to huge images, try to not keep images in memory, load images only on demand(with some cache strategy)
Try to replace picasso with glide. Glide provides better memory performance https://medium.com/#multidots/glide-vs-picasso-930eed42b81d
Try to load all your images with closest context
https://stackoverflow.com/a/32887693/6193843
1)It is considered a good tactic to recycle all bitmaps and data at activity's OnStop method.
2)It's also considered a good tactic to use a retainer Fragment to avoid recreating data at every configuration change.
But I don't see how these two can be combined?
Let's say I use a fragment to load a bunch of bitmaps...At OnCreate I check if that Fragment is null or not to get it's data or to instantiate a new one to create them. If i recycle all my bitmaps at OnStop() then there will be nothing left retrieve at the configuration change cause all data will have been recycled.
So....I don't see any way to combine these two tactics. Am I wrong? And if not which of the two is best to use?
My case is about loading images from SD card folder. could be only one pic, could be 500...
and showing pictues isn't all my app does so after this activity there could a need for memory by some other activity.
From Managing Bitmap Memory:
On Android 2.3.3 (API level 10) and lower, using recycle() is
recommended. If you're displaying large amounts of bitmap data in your
app, you're likely to run into OutOfMemoryError errors. The recycle()
method allows an app to reclaim memory as soon as possible.
According to this you don't even need to call recycle on devices running API 11 or higher, so it may not really be a problem for you.
You also really don't need to recycle bitmaps if the app is being destroyed as the system is going to reclaim all memory the app is taking up to begin with.
Recycle is only needed if you are showing a massive amount of bitmaps or large bitmaps and need the memory reclaimed in your app while it's still running.
Another thing to note is with the strategy you're trying, you wouldn't clean resources in the Activity's onStop() but rather the retained Fragment's onDestroy(). OnDestroy() on a retained fragment won't be called on configuration change because the Fragment isn't ever being destroyed. Thus, your resources can stay in memory beyond your Activity's lifecycle and will be destroyed at the end of your Application's lifecycle.
In my APP, Activity-A triggers another Activity-B. Activity-B triggers another Activity-C. Now the control return to the Activity-A from Activity-C Via Activity-B. The Activity-A uses the Bitmap image to draw as a background in its Canvas.
Question:
When I move from Activity-A to B, Do I need to recycle the bitmap variable (eg. background.recycle()) in onPause() method ?
Assume, I recycled the bitmap variable in onPause() method. Will this be a good approach to avoid OOM error ( keep in mind that the image has to be re-drawn when it comes back to Activity-A)
Do you get OOM errors? If not (since your bitmap is not big) then simply do nothing ... The docu says about the recycle method:
This is an advanced call, and normally need not be called, since the
normal GC process will free up this memory when there are no more
references to this bitmap.
So there is also a main difference between Android 2.x and Android 4.x. In Android 4 the bitmap memory is no longer managed natively, but is part of the normal java heap and works like every reference works: If the there is no reference anymore, then the garbage collector will collect the bitmap somewhere in the future.
Wherer is the right point to call recycle? Well the right point will be, when the Bitmap is no longer displayed on screen. so onPause could be a possibility, but keep in mind that you have to reload it (async) in onResume. So whats the problem with that approach? Once you have marked the Bitmap to be no longer needed by calling recycle() the bitmap is no longer useable, but probably has not been GC collected yet. So if the user jumps from Activty A to B and will return quickly, it's possible, that you have the same bitmap twice in memory, because the GC has not collected yet the first (recycled) bitmap.
So my tipp is: Try to reduce the bitmap size if you have memory issues. Use less quality bitmap (have a look at Bitmap Options). But I guess you need to try diffrent strategies to find the best working one for your app.
every time you don't need the bitmap recycle it. using
if method at least to avoid force closing in some cases.
if (null != bmp){
bmp.recycle();
}
and i advice you instead of sending the Bitmap between activities get its filename by using intent and pass it through your activities like this you will avoid re-drawing the bitmap in every activity and that will cause OOM for sure.
I'm working on an application which has about 4 to 5 HorizontalScrollViews. Out of these, 3 are completely loaded with images. To get this working I had to overcome java.lang.OutOfMemoryError, many times. Thanks to all the friends on stackoverflow. Now, my next activity is again going to be filled, completely, with images. Therefore, I wanted to know whether heap is freed when a new activity begins?
If you will kill the previous activuty using finish() then it will not use heap memory else it will us else memory being in the background(stack).
Sorry if this is some kind of duplicate question. I googled for about an hour but still have problems with the memory usage of the WebView component.
I'm starting an Activity (NewsDetail) from a ListActivity to display a specific news article. The HTML-Code of the article is added into the WebView which is included in the Activity layout. (it also loads 1 or 2 images via newsDetail.loadDataWithBaseURL())
I'm starting the article Activity via:
Intent i = new Intent(getApplicationContext(), NewsDetail.class);
i.putExtra("position", position);
startActivity(i);
After reading this question, I changed my Layout so that I add the WebView programmatically:
newsDetail = new WebView(getApplicationContext());
In my onDestroy method is set:
public void onDestroy(){
super.onDestroy();
newsDetail.destroy();
newsDetail = null;
finish();
System.gc();
}
After a while, the Garbage Collector reduce the amount of memory from about 4 MB to 2 MB. If I open/close several news articles it rises to a critical heap size. :/
As mentioned, after destroying the activity, there's a rest of 2 MB left to the activity (which doesn't exist if I completely remove the WebView from the code). So it seems to have sth to do with the WebView itself.
The same problem is mentioned here.
I also set:
android:noHistory="true"
Has anyone of you an idea how to completely get rid of memory usage of the "NewsDetail" Activity after returning to my ListActivity?
Would be glad to hear any ideas, this is driving me crazy. Is there a chart for Android phones providing more than 16 MB heap size?
I think its a known bug. Please refer to this official http://code.google.com/p/android/issues/detail?id=2137
you can refer to this link to let one know that this is a known issue or such
There is a mParent reference which points to the ViewGroup that contains the WebView and eventually to your Activity. WebView leaks anything it can get its hands on, so you have to remove it from the view hierarchy.
See my answer here:
Memory leak in WebView
If your onDestroy is located in the newsDetail activity, it's kind of weird code.
First you do super.onDestroy() which should do what you want so the object is flagged for GC. But in the line after you reference the same object. I'm no expert but that might cause troubles.
If the onDestroy method is inside your listActivity, it makes sense that it doesn't work because the method is never called as the listActivity stays open while other newsDetails are opened.