On Apr 12, 2012, at 8:02 PM, King Coffee wrote:
> I'm using the following code to allocate an image file to a ImageView 
> control, with instance name: image.
> 
> Bitmap bitmap = BitmapFactory.DecodeFile(matches[0]);
> image.SetImageBitmap(bitmap);

I've tried to expound upon this [0, 1], and I'm probably still not being clear 
enough, so let's flip the question around...

When _shouldn't_ you call Dispose()?

You shouldn't call dispose when the runtime type is a C# type, the instance has 
a peer held in Java code, and Java peer will be re-entering managed code.

Every Java.Lang.Object subclass has a corresponding (generated) Java peer type 
[1]. When you create an instance of the Java.Lang.Object subclass, you also 
create an instance of the Java peer type, and the Java peer and managed 
instance are associated with each other. Calling Dispose() breaks the 
association.

The problem with breaking the association is that once broken, if the Java peer 
re-enters managed code, a new Managed Callable Wrapper (MCW) will be 
instantiated, and a new mapping between the Java peer and the new MCW will be 
created. If you had any instance state, it will be "lost", which can be quite 
confusing. (Or you'll get an exception because the MCW type doesn't provide an 
(IntPtr, JniHandleOwnership) constructor...)

Note that this only really applies to C# types. If you're only dealing with 
Java types, you can dispose of the managed wrapper with (near) impunity; a new 
wrapper will be create if (when) the Java instance is (re-)exposed to managed 
code.

That is the fact with Bitmap: BitmapFactory.DecodeFile() will _never_ return C# 
type that contains C# instance state. Consequently, there's no need to ever 
preserve the association (unless you're storing `image` as a class member), so 
you can kill the mapping as soon as you're done with it:

        using (Bitmap bitmap = BitmapFactory.DecodeFile(matches[0]))
                image.SetImageBitmap(bitmap);

The result of the above is that only Java code will refer to the Bitmap 
instance, so when your code later changes the image's bitmap, Android will be 
able to quickly release the Bitmap instance.

> I tried to dispose of the control's context as follows: 
> image.Context.dipose(), image.CacheDir.dispose(). 

That won't hurt, but it won't really help either. As mentioned above, if there 
isn't a wrapper for a Java instance, one will be created when the Java instance 
enters managed code, so the next time you call `image.Context` you'll simply 
get a new wrapper. (If you have an e.g. Dictionary<Context, object> you'll 
likely invalidate your keys if you do that, too. Care must be taken.)

> But, do I real need to dispose of container control, image? and reassign it?

I don't think you'll need to dispose of the container control, I imagine that 
just disposing of the image will be sufficient.

 - Jon

[0] 
http://docs.xamarin.com/android/advanced_topics/garbage_collection#Helping_the_GC
[1] 
http://docs.xamarin.com/android/advanced_topics/architecture#Managed_Callable_Wrappers

_______________________________________________
Monodroid mailing list
[email protected]

UNSUBSCRIBE INFORMATION:
http://lists.ximian.com/mailman/listinfo/monodroid

Reply via email to