Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Consequences of drawable.setCallback(null);

While trying to implement small in-memory cache of Drawables, I learned that to avoid memory leaks after closing activity I need to unbind those Drawables: set their callback to null.

Because maintaining Drawables cached in each activity would require extra code, I tried to unbind them immediately after setImageDrawable(drawable) and I don't see any consequences so far.
This is code from MyImageView class (extends ImageView):

setImageDrawable(drawable);
d.setCallback(null);

In debugger I can clearly see that before first line callback is null, after first line it is set to this imageView, and after that I set it to null again. It is normally shown after that..

Documentation for setCallback (Drawable.Callback cb) states:

Bind a Drawable.Callback object to this Drawable. Required for clients that want to support animated drawables.

Since I don't need animated drawable, I don't see why I shouldn't do this but it bothers me that in several blogs about memory leakage in Android concerning drawables this is done only after activity is done. Question is, why is callback always automatically set when binding to ImageView?

Are there some border conditions where those drawables with callback set to null will cause a problem? Not displaying or NPE?

like image 368
CloudWalker Avatar asked Oct 04 '11 13:10

CloudWalker


People also ask

What is android drawable?

A drawable resource is a general concept for a graphic that can be drawn to the screen and which you can retrieve with APIs such as getDrawable(int) or apply to another XML resource with attributes such as android:drawable and android:icon . There are several different types of drawables: Bitmap File.

Which of the following method of the drawable class allow the client to interact with the drawn object?

In addition to simple drawing, Drawable provides a number of generic mechanisms for its client to interact with what is being drawn: The setBounds(Rect) method must be called to tell the Drawable where it is drawn and how large it should be.

Which of the following ways defines and instantiates the drawable class?

There are two ways to define and instantiate a Drawable besides using the class constructors: Inflate an image resource (a bitmap file) saved in your project. Inflate an XML resource that defines the drawable properties.


1 Answers

You should not cache Drawables -- the Drawable object is very stateful, and intended to be used by one and only one owner.

If you want to implement a cache, you should be caching the drawable's constant state.

The constant state is retrieve with this:

http://developer.android.com/reference/android/graphics/drawable/Drawable.html#getConstantState()

(Note this method can return null; not all Drawables have constant state.)

You can later instantiate new Drawables from a constant state with this:

http://developer.android.com/reference/android/graphics/drawable/Drawable.ConstantState.html#newDrawable(android.content.res.Resources)

Also keep in mind that Resources already maintains a cache of Drawables for you, using this facility, so there is no need for you to implement your own cache for any Drawables you are retrieving from Resources.

And if you are making your own Drawables outside of resources, I would strongly recommend making a cache of the underlying data (such as a bitmap downloaded from the network) then trying to mess with the constant state. (And again, definitely don't cache Drawable objects themselves.)

like image 200
hackbod Avatar answered Oct 20 '22 00:10

hackbod