After painfully finding out that Typeface.createFromAsset can create memory leaks, I am trying to find a full workaround. The caching solution described in the above link helps to avoid having to reload fonts repeatedly while the application is running. But how about cases where your app has to start again from onCreate (e.g., after orientation changes, other apps popping up in between etc.)? Is there any way to store the typeface(s) in onSaveInstanceState in order to avoid having to call again Typeface.createFromAsset and leaking memory every time?
Related
I have an LRUCache that I use to cache thumbnails and other such small bitmaps. Currently, I'm using it in my main activity, however, I'd like to use it my other activities too. This makes me wonder if it's a good idea to simply store this LRUCache object in my custom application singleton (which extends Application) and solve the problem of accessing the cache in other activities. The reason why I'm concerned is because, as I understand it, if the application process is killed - which is very likely to happen when the app is left running for too long in background - the application object and therefore the cache will get garbage collected. Correct me if I'm wrong on that and help me understand this issue better/provide a solution to this problem.
My usual rule of thumb is, for persisted data use disk cache & for quick, dirty & light data, use memory cache (or your lru cache). Be careful with storing bitmaps in memory cache, at least for android devices < 2.3.3, I believe. The pixel data of the bitmap is actually stored in native memory so developers have less control to encourage garbage collections for it. For example, even setting your bitmap to null or invoking the recycle() method may not fully convince the garbage collector to free the bitmap in the dalvik heap (vm heap) since its a small object on the dalvik heap (vm heap), even though it's native counterpart in native memory is large cause OutOfMemoryException.
Sorry for straying off a bit but thought you should know. As for your the answer, your assumption is right. When android is running low on memory it retains the last user activity instance in it's system memory but may kill your process, where your process hosts your application object. So in your case, if you stored 5 bitmap objects in your application object, and users left for sometime, they may come back to an activity requesting a bitmap from a newly created application object by the system, which would then produce a null bitmap.
Given these circumstances the solution is typically clear. If you want to persist data, you can't trust object memory (in-memory, RAM), at least on Android, so disk memory might be your best option.
Hope this helps.
I think this is a perfectly fine idea. Here's a video from Google I/O 2012 with some relevant information: http://www.youtube.com/watch?v=gbQb1PVjfqM
My android app is taking more and more memory over time. I took a heap dump and analyzed it with MAT.
Here's the main leak suspect :
So it seems like one of my activities isn't cleared from memory after I quit the app (with back button) then when I restart the app a new instance is created and fills in the memory.
Now if they're PhantomReferences why the memory isn't cleared after a while or when I quit the app? The memory is never cleared even when I use other app etc. The only way to completely close the app is to use a task manager to manually kill the app.
What can I do to avoid this anarchic memory consumption ?
EDIT:
I found the problem!
Each activity was setting up a CustomExceptionHandler with Thread.setDefaultUncaughtExceptionHandler() and that CustomExceptionHandler was keeping a reference to the context. So I got rid of the context reference and I 'nulled' the DefaultUncaughtExceptionHandler in the onDestroy() method. That's really better now!
I would use the dominator tree functionality of MAT to find out what is above those references, this may give you an idea of which Activity is the culprit.
Make sure you haven't passed a Context anywhere and held a reference to it, this is a classic android memory leak and it's really easy to do!
Although some static analysis tools frown on this, in the onDestroy() methods of your Activity you can null all your local variables (except primitives), it helps to nudge the garbage collector sometimes and can make for an easier to analyse heap dump in MAT.
Some generic approaches to reduce size of the app what I generally follow is this :
Call finish() below passing an Intent to next activity, this will avoid piling up of stack and helps in gc(garbage collection)
If you are not using shared preferences to save data, flush them at exit by calling System.exit()
If you find any drawable images/layout xmls/java classes which you are not using in your final program, ensure you remove them from the project
Images have to be .png since JPEG images take lot of memory.
In case of using database(sqlite, internal database etc), a better approach would be using "try/catch/finally" blocks, In try you open the db, in finally you close it, which will avoid memory leaks caused because of not closing cursors or databases.
Use AsyncTask instead of threads. in onPostExecute()function, close the progress dialogs if any.
hello friends
i have develop one application in which i have lots of images and sound,
i can release sound easily by release() method but i can't able to release image.
can you tell me how can i release image ?
earlier i have use system.gc() function but it is not working for image i thing it is garbage collector.
second thing is that can you give me precaution step against memory management (regarding of image,sound & codeing part also)
Thanks
nik
Invocations of System.gc() are only suggestions to run the garbage collector. The GC need not run immediately.
I believe such complex applications would benefit from using an MVC model. The Model (or logic) class can save the required images and sounds to a cache folder, and just pass the list of file paths to the view (Activity) which can read and display on-demand, de-referencing any assets that are no longer required.
Also, it would help to reduce the asset sizes (images and sounds) by lowering resolutions (image) or downsampling (audio), wherever possible.
Update:
- For downsampling images, check this link: http://developer.android.com/reference/android/graphics/BitmapFactory.Options.html#inSampleSize
MVC is slightly tougher to implement in Android due to the fact that Activities are the entry points. So, what can be done is that a singleton "Model" object can be created, which can be accessed from anywhere. Similarly, a singleton "Controller" object can also be created. The activity can notify the controller when it requires an asset, and the controller will forward the request to the model.
My app is crashing after longer use - runs out of memory.
I am closing all activities after switching to next one, but I still have that problem.
Is it possible to programmatically clear cache / memory, so application does not run out resources?
Can I use getCacheDir() to accomplish that?
Apparently your app is leaking memory. Make sure you clean up unused resources, close databases, reuse variables, etc.
Also refer to this post on how to track down memory leaks and how to avoid them.
I have an app that only requires the value of a textview field to be saved... what would be the most simple and efficient way to save such a small amount of data? Creating a database for this seems like overkill. would onSaveInstanceState be sufficient?
This sounds like a job for SharedPreferences.
You could also consider saving it to cache. Keep in mind if you use internal storage for your cache, it may be deleted if there is low memory. Using Shared preferences also works as Yoni had mentioned and will ensure that the data is not deleted even if on low memory.
SharedPreferences is the easiest if you want it to be persisted across sessions.
I think onSaveInstanceState will not survive a closing of the whole application like it will happen if you shut down the phone or your app crashes.
Go with the sharedPreferences Yoni mentioned. They will make your data persistent on the phone memory without much work for you.