I have simple android app. App includes around 50 images, mostly PNG format, but also most of them are icon size. There is about 5 layouts and use Google maps and WebView. App itself weights bit under 6MB.
Then i run all of app options and then i look into app settings -> cached processes, i see my app uses 70 MB of RAM !!!
Im calling finish() method wherea i can, but that doesnt help. What could help to reduce memory use ?
Even Angry birds is using less !
It might be that you're loading your Bitmaps with methods that create immutable Bitmaps and not releasing them adequately (you have to take care to dispose of all of their references or else the garbage collector will never free the space they're using.
If that's the case, this reference might help you with the Bitmaps you're using.
The best way is to use 9 patch PNG images for your application. This will definitely help you to reduce cache size as well as application size. More over deploy you application code according to android life cycle, excessive use of finish() make the activity to onpause() state, so use onDestroy() where you want to kill that activity.
Create a drawable folder and put all those 9 patch image there.Deploy onDestroy() to fill the activity
Please compress each and every image without affect image quality and then take care of leaked memory. Each activity action completed then finish that activity. once you exit from application. destroy all running methods. if you need to clear memory manually, by calling the .recycle() method of your bitmap object.I think its help you to reduce memory.
Try something like this, it may help i guess:
#Override
protected void onDestroy() {
super.onDestroy();
unbindDrawables(findViewById(R.id.LayoutId));
System.gc();
}
Related
I have the user's profile pic across multiple activities in my app. Once, they change their profile image, I want to make sure that all my Glide instance's cache are cleared. That way when they navigate around the app, they can see their updated profile pic.
Currently I'm using this method: Glide.get(activity).clearDiskCache(); and that only clears the Glide cache for that activity and not across my app.
Hope someone has a quick solution, where I don't need to call the .signature() function for each glide instance in each of my activites. Or clear each glide cache in each activity.
Try
Glide.get(context).clearMemory();
OR
Glide.get(context).clearDiskCache();
Note: clearMemory() must be called on the main thread. clearDiskCache() must be called on a background thread. You can't call both at once on the same thread.
I went through this whole windmill trying Signatures and clearing caches, and to be honest - none of those options work particularly well and they're usually slow.
Glide's first recommended solution is bar far superior, although it can sometimes take a bit more time to rework your code. I eventually lost my marbles and made the necessary changes to my code. It was well worth it.
Solution: Change the image name of the image when the user uploads a new image. Get the file name and use that. Once the image URL has changed, Glide understands you have changed the image and will update the Cache accordingly.
I am using a BitmapFont as follows:
create(){
font = new BitmapFont(getFileResource("50.fnt"), getFileResource("50.png"),
false);
}
dispose(){
font.dispose();
}
I have several screens that load and unload fonts of different sizes. As time goes by, the memory fills up.
After spending a long time looking for a memory leak, I find this BitmapFont class is leaking. I think it is leaking on native memory because the leak is not seen using Memory Analyzer.
I am following the procedure to clean up the memory according to the current documentation. But this is not enough. What else should I do to ensure the BitmapFont lets go of its memory ?
This might be a bug. Here you can see your constructor. And here a very similar one. The difference is that the 2nd sets the ownsTexture flag. Only if this flag is set, the texture gets disposed.
I will create an issue/PR to fix this problem or at least make it behave the same way, or add a JavaDoc warning.
For now you can solve this problem by doing bitmapFont.setOwnsTexture(true) yourself.
The error was that the libgdx code is long running, so I could not wait for dispose to be called.
So I was calling dispose on the elements that were no longer needed on the screen from a thread other than the GLThread (on Android)
Libgdx ignores dispose() when not coming from the GLThread().
Adding the clean up code on render such that it runs when outdated components pile up fixed the problem.
I have an application that uses a flip-book style animation with thousands of images. APK size isn't an issue due to it being an internal only application that will never be put on any app store.
The issue I am having is my animator is a sub-classed ImageView that switches out images at 15 frames per second and each time I call setImageURI Garbage Collection then runs. So is there an alternative method to setImageURI that wont cause Garbage Collection to be run?
Edit: A little more background information.
My app has ~12 sequences and 6 of them contain 1609 Images and different events need to be called at certain frames. Another need is for the user to be able to stop on any frame to survey the situation and either preform an action or continue down the sequence. A 3D engine would have been the ideal solution but this method was brought up as the user doesn't need complete freedom and is on a "rail" the entire time.
This is the meat of the application and where the problem occurs
try {
((BitmapDrawable) getDrawable()).getBitmap().recycle();
setImageURI(imgUri);
refreshDrawableState();
} catch (Exception e) {
e.printStackTrace();
}
The Garbage Collector is running because you're exchanging one image for another which dumps the previous. It's going to happen every time you lose references to the images.
Here are a couple possible methods to consider.
Since you mentioned it's a flipbook, build and assign an AnimationDrawable to the ImageView which will act as a frame-by-frame animation (exactly what a flipbook is). This loads all the images at once and will keep them around until you lose a reference to the AnimationDrawable.
Store all the images as SoftReferences to cache the images. A SoftReference will keep the object in memory until memory is needed to be collected. This will slow the frequency of the garbage collector (assuming this is the cause). Use BitmapFractory to build the image and setImageBitmap to assign it to the ImageView. The other advantage of this is it allows you to build images on threads before you assign it to the ImageView.
Maybe it's because your Image need to much memory, and the android need call the GB to free more mem trying to avoid crashing your program
So, I'm using custom number tiles for images. The images are stored as resources. I've been tracing a memory leak, and have cause to believe the method I am storing these images for use is suspect. Currently, I'm doing this:
private void loadImageList()
{
Log.d(TAG,"Reloading List "+imageList);
if (imageList==null || imageList.size()<10)
{
imageList=new ArrayList<Bitmap>(10);
imageList.add(0,BitmapFactory.decodeResource(getResources(), R.drawable.ant_number0));
imageList.add(1,BitmapFactory.decodeResource(getResources(), R.drawable.ant_number1));
imageList.add(2,BitmapFactory.decodeResource(getResources(), R.drawable.ant_number2));
imageList.add(3,BitmapFactory.decodeResource(getResources(), R.drawable.ant_number3));
imageList.add(4,BitmapFactory.decodeResource(getResources(), R.drawable.ant_number4));
imageList.add(5,BitmapFactory.decodeResource(getResources(), R.drawable.ant_number5));
imageList.add(6,BitmapFactory.decodeResource(getResources(), R.drawable.ant_number6));
imageList.add(7,BitmapFactory.decodeResource(getResources(), R.drawable.ant_number7));
imageList.add(8,BitmapFactory.decodeResource(getResources(), R.drawable.ant_number8));
imageList.add(9,BitmapFactory.decodeResource(getResources(), R.drawable.ant_number9));
}
}
public void onStart()
{
super.onStart();
loadImageList();
}
What will happen is if I open and close this application repeatedly, then the system won't have enough memory to add an image to the ImageList. I'm setting the image of the button like this (But with an object ImageButton, of course). I should add that the application is threaded, and this call resides in a runOnUiThread(Runnable)
ImageButton.setImageBitmap(imageList.get(current_var));
I've tried deleting the images in the onStop() command, but it will sometimes cause a crash when the thread tries to allocate the image stored in memory to the button, due to the threaded nature of the beast.
So, is there a better way that I can load these images that won't cause a memory leak?
I realized something after posting this. I could just make the imageList static. These images aren't going to change from one view to the next. The Bitmaps don't contain a view, so the memory won't lock up. I'm already checking to see if the values exist before I'm using them. And this function is used so frequently that holding on to static memory won't hurt other aspects of the program. Sometimes it just helps to put it into words..
I have a bitmap that I load from the SD card by allowing the user to choose a picture to display. Once the bitmap is created, I set the Bitmap in an ImageView:
mBitmap = Bitmap.createBitmap(Media.getBitmap(this.getContentResolver(), mPictureUri));
mImageView.setImageBitmap(mBitmap);
This works fine. But, if I change the screen orientation from portrait to landscape, and back again a few times, I always get an OutOfMemory exception.
In onPause, I call mBitmap.recycle(), and then on onResume, I call the above code again to create the bitmap and set the ImageView. Since I'm recycling the image each time, how can I get an OutOfMemory error?
In any case, since that failed, I found a post that said to try using onRetainNonConfigurationInstance() and getLastNonConfigurationInstance(). See post Save cache when rotate device. I changed my code to work this way, and I still get an error. Changing the code, I had the call to getLastNonConfigurationInstance() in onCreate(), and removed all code in onPause and onResume.
Can someone tell me what the problem is, or provide some way to simply load an image, and then be able to pause and resume the Activity without running out of memory? Thanks.
Try reducing the size of your bitmap. How big is it? Use BitmapFactory.options.
Also instead of using "this instance". See the article about memory leaks:
http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html
The memory leaks could be due to holding on to the context instance which in turn contains references to all the objects from the Activity before it was destroyed.
The article explains it better.
You should reduce size of the images because there is 16MB per app, if you have large bitmaps being recreated, they could accumulate to 16MB before they are garbage collected or if there are memory leaks.