In my app there are two activities viz A and B.
Activity A:
It has a list which displays information about an item briefly. When an item on A is clicked, it loads Activity B.
Activity B:
It has two web views and several listviews. Top of the activity is occupied by header web view. Lower part of activity has tab host, this hosts the second web view in first tab and remaining tab each hosts a list view.
Problem:
When user navigates from A to B, the heap size increases significantly. Even after I navigate back from B to A, heap size continues to be the same. There is not even a byte decrease, in fact it increases sometimes. Yes its because of these web views. I have read about web view memory leaks on SO and other sites. I followed approach mentioned here
Added web view dynamically inside a container[RelativeLayout]. Removed webview on activities onDestroy
Sub classed web view as suggested in the SO article
Cleared web view cache every time etc
No matter what heap size does not come back to what it was before navigating to B.
Really appreciate if someone can guide me to a possible fix
Note:
I have already read this and followed this issue on SO.
Memory leak in WebView
Edit:
I have tried without web views in B and the increase in heap size is very very less around 0.5 MB but with web views it creases by 4-5 MB
Heap size logs ( got by following suggestion mentioned here )
onCreate B
debug.heap native: allocated 4.11MB of 4.17MB (0.01MB free) in []
debug.memory: allocated: 12.00MB of 96.00MB (1.00MB free)
onDestroy B
debug.heap native: allocated 8.66MB of 10.08MB (0.48MB free) in []
debug.memory: allocated: 12.00MB of 96.00MB (1.00MB free)
on Resume A
debug.heap native: allocated 7.94MB of 10.08MB (1.32MB free) in []
debug.memory: allocated: 12.00MB of 96.00MB (0.00MB free)
I cross checked the numbers by taking heap dump before and after B is started and destoryed, heap size are quite close to the one I get it in logs
I followed series of steps and got the memory footprint reduced. This is what I did,
instead of creating webview statically via xml I now create webview programmatically and add it to a container. Once webview is no longer needed I remove the webview from the container then I remove all views from webview and call destroy on it. Eventually memory allocated reduces.
private void releaseWebView() {
webViewContainerRelView.removeAllViews();
if(mWebView != null){
mWebView.setTag(null);
mWebView.clearHistory();
mWebView.removeAllViews();
mWebView.clearView();
mWebView.destroy();
mWebView = null;
}
}
I call releaseWebView() from onDetachedFromWindow method of Activity as below.
#Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
releaseWebViews();
}
Related
I have a NativeContentAdView in a ListView item. When I call setNativeAd(NativeAd) on it, a noticeable lag happens. All AdMob class and method names are mangled (zzdt, zzalp, zzow etc) so I omit them.
Things AdMob performs in View#onAttachedToWindow callback:
registers several BroadcastReceivers (each requires a Binder transaction) (sum ~10 ms)
Things AdMob performs in OnScrollChangedListener#onScrollChanged:
dozens of DP-to-PX conversions, calling Display#getMetrics and triggering a Binder transaction for each conversion (sum ~7 ms)
generates some JSON (~8 ms)
evaluates some JS (~7 ms)
creates a WebView instance (~5.5 ms), sets it up (~9 ms), asks it to loadUrl (~7.5 ms)
Inside Handler#handleCallbacks (i. e. Handler#post):
Creates a WebView, sets it up, adds to Window and evaluates JS (~27 ms)
Gets packageInfo (IPC), creates a WebView, sets it up, asks to loadUrl, checks permissions (IPC), parses JSON, gets packageInfo one more time, introspects resources via Resources#getIdentifier, gets activityInfo (IPC) (sum ~40 ms)
Obviously, all these heavyweight operations are leading to jerky scroll.
What should I do to avoid lags or what I'm possibly doing wrong? Why don't AdMob native AD is as slow in other applications I've seen?
Using AdMob/GMS v. 10 and/or 11, but 16 shows the same lags.
All measurements are taken with Nanoscope on their special emulator, but lag on a real not-so-old Nexus 5 is even worse.
I'm developing application for Android(Xamarin). At current moment is like prototype(inside nothing heavy).
I added app7compat support library and also implemented toolbar with navigation Drawer Layout.
I make some test on real device(Samsung Galaxy S4 Active) and it's an like glitch/bug,because when application started,android device monitor showing this :
How that is possible? My activity contains:
Toolbar(with Drawer layout)
Some different controls,like imageView and imageButtons
As i said,that comes from start(i mean that this 86% used memory allocated with strange items,because there is no computing logic).
Why this happens? Thanks!
As guys explained for me,that is ok,because from start application eats 86% of allocated memory(after that if needed, will grow up).
Anothers tip was,to put flag largeHeap and via RunTime(),to see how much memory can be allocated:
Runtime rt = Runtime.getRuntime();
long maxMemory = rt.maxMemory();
Log.v("onCreate", "maxMemory:" + Long.toString(maxMemory/1024/1024));
and my result(Samsung Galaxy S4 Active) was :
512MB
Hope that helps!
I would like to make an mobile application, what contains a lot of picture
My question how can I dynamically open the picture and delete from memory?
I tested this:
a = Texture.new("a.jpg")
print(Application:getTextureMemoryUsage()) -- write x
a = nil
print(Application:getTextureMemoryUsage()) -- write x again
Thanks for help.
Problem is that garbage is not collected right away and that is why memory is not freed right away.
You could try calling collectgarbage() couple of times to force it as:
print(math.floor(collectgarbage("count")))
collectgarbage()
collectgarbage()
collectgarbage()
print(math.floor(collectgarbage("count")))
i have an Android app that displays alot of images, it works, the images are gatherd from an url, added to a que and gathered by 4 threads,stored in a cache and then displayed in a listview view 4 images for row, there are abot six rows at each time on the screen. There is a total of usually 90 images.
The rows(and imageviews) are always recycled, so the amount of items is always the same and i'm not initializing anything.
This seems to work quite fine, i have always an average used heap size of 13MB.
The problem i have is that at the beginning mi max heap size is quite small and i get GC messages like:
01-20 16:48:39.191: D/dalvikvm(9743): GC_FOR_ALLOC freed <1K, 31% free 12048K/17351K, paused 25ms
but the more i scroll up down the view the heap size grows more and more untile i get things like
01-20 17:02:05.339: D/dalvikvm(11730): GC_FOR_ALLOC freed 544K, 72% free 13871K/49159K, paused 35ms
as you see even if the used is the same the maximum is increased even if i never got to that limit. and the true problem is that at this point i start to get outofmemory errors.
Can someone explain me what's wrong?
Thanks!
What version of Android are you using? If you're testing on pre 3.0 (ie 2.x), the byte arrays that store most of the information in Bitmaps are allocated and stored in native memory. This means that in heap dumps and in the GC notifications, you only see the small amount of memory used for pointers in Bitmaps, rather than the actual size.
For more information check out this google IO talk on memory management and detecting memory leaks: http://www.youtube.com/watch?v=_CruQY55HOk
Also I've worked on several apps doing similar things. My guess is that either your cache size is way too large, or (more likely) the images you're displaying and storing in the cache are much larger than the size you actually want. If you display a bitmap in an image view, the imageview will store the original bitmap in memory, even if it is significantly larger than what would actually fit in the view. Try resizing the images from disk to at least closer to the appropriate size before trying to display them: How do I scale a streaming bitmap in-place without reading the whole image first?
To cache my Images I use Map<String, Drawable> drawableMap. On a OutOfMemoryError I call this function:
private void cacheLeeren()
{
int size = drawableMap.size();
int del = (int) (size * 0.3);
Set<String> s = drawableMap.keySet();
for (String t : s)
{
if (del >= 0)
{
drawableMap.put(t, null);
del--;
}
}
}
I think it's not the best way...but it works ;-)
My guess is that your app reaches a very high peak of memory usage for a short time. It's true that on average you only use 13MB but if your heap grows to as much as 50MB, it means that momentarily you've consumed much more memory than you're thinking.
Let's try to figure out where this is happening. You've mentioned that you're using an LRU cache. This cache frees memory as soon as it fills up. My guess is that you're starting to free memory too late, and this memory isn't freed immediately - since it depends on the system GC. Whenever you're freeing some items from the cache, try to call System.gc() manually.
You've also mentioned that you're calling Bitmap.recycle(). To the best of my knowledge this is useless on Android 3+ because the native heap is no longer used for bitmaps. Since all bitmaps are on the dalvik heap, they will be freed by the GC.. You can't rush this like before unless you call System.GC() yourself.
Another idea for your source of problems is heap fragmentation. See my previous SO answer to a similar issue in this question.
I get a clasical "VM budget excedees memory - out of memory" type error crash report from the Android Market.
I checked the app for memory leaks over and over again. This error happens on a very small percent of total application installs, around 1-2% and it always happens on start-up. The app loads some bitmaps from internal memory for each activity, but does not crash on most devices. I thought all applications had a guaranteed minimum stack size for bitmaps so this should work for every device. Min SDK is 7.
Any reason why ? Does this sound familiar to anyone ?
I had quite a similar problem, and my images were simply too big for some devices.
I have read that you have one image per Activity and I guess this happens when switching from one to another as the newly allocated Drawable cannot fit. What you could do, to save some memory, would be to unload the background image of the Activities that are not shown:
#Override
protected void onResume() {
super.onResume();
Drawable d = loadMyDrawableFromDisk();
setBackgroundDrawable(d);
}
#Override
protected void onPause {
setBackgroundDrawable(null);
super.onPause();
}
It may help as the memory will be freed a few after onPause() is called, and not when the underlying View of your Activity will be unallocated by the system.