How Do You Force A NinePatchDrawable to release the BitMap bytes it parsed out of 'res'?
As an Android developer I face pressure to control memory utilization in my games.
I work to control memory utilization by releasing resources as quickly as I can after they are no longer used. To this end, I maintain a list of all loaded resources and purge / release them from memory as soon as I am done with them.
My application uses a number of different types of graphical resources
- BitMap
- BitMapDrawable
- Drawable 开发者_如何转开发
- NinePatchDrawable
How do I release these objects right now?
- BitMap : I use the "recycle()" method
- BitMapDrawable : I use the "getBitMap().recycle()" method
- Drawable : I set these to null (not working)
- NinePatchDrawable : I set these to null (not working)
What have you tried?
- You cannot "getBitmap()" a NinePatchDrawable
- You cannot convert a NinePatchDrawable to a BitMapDrawable (even if they are both Bitmap based Drawables)
- There seems to be a way to parse the PNG yourself, feeding the bytes into NinePathDrawable yourself -- this might get me to a point where I can just "recycle()" the underlying BitMap myself, but that seems like I'm reinventing the wheel (http://code.google.com/p/android/issues/detail?id=13542)
My Current Rules:
- Never use @drawable/ in XML
- Never android:background in XML
- Never android:src in XML
To be able to use: @drawable/, android:background, android:src in xml, you can always use custom classes.
So instead of
<ImageView android:src="@drawable/bg" />
you can use:
<com.myPackage.CustomImageView android:src="@drawable/bg" />
Than in the CustomImageView in the constructor you can get the references to your xml attributes:
private Drawable bg2;
private Drawable bg1;
public void CustomImageView(Context context, Attrs attrs)
{
super(context, attrs);
// Use this to get references to your xml attributes
int resourceId = attrs.getAttributeResourceValue("android", "src", 0);
bg1 = getResources().getDrawable(resourceId);
// Or for the 'background' attribute
resourceid = attrs.getAttributeResourceValue("android", "background", 0);
bg2 = getResources().getDrawable(resourceId);
// Now you can recycle() your 'bg' whenever you're done
}
This way, you can extract references from your xml. And recycle() them when you think it's appropriate
I too am frustrated by the outofmemory bug. My application was throwing an outofmemory error whenever the user went from one activity to another. Setting my drawables to null and calling System.gc()
didn't work, neither did recycling my bitmapDrawables with getBitMap().recycle()
. Android would continue to throw the outofmemory error with the first approach, and it would throw a canvas error message whenever it tried using a recycled bitmap with the second approach.
I took an even third approach. I set all views to null and the background to black. I do this cleanup in my onStop() method. This is the method that gets called as soon as the activity is no longer visible. The onDestroy() method might not get called. Also, if the cleanup is done in the onPause() method, users will get a black screen before moving onto the next screen.
To prevent a black screen from occurring if the user presses the back button on the device, I then reload the activity in the onRestart() method by calling the startActivity(getIntent()) and then finish() methods.
Note: it's not really necessary to change the background to black.
精彩评论