My friend pointed out a very interesting construct used in the Android native app, Contacts.
I learned a couple of things along the way.
Firstly what are weak references? Well you need to know what is a strong reference. In Java, there is a garbage collector at work that removes dead objects from the heap. An object is dead when its reference goes out of scope.
So supposing I write a code
void foo()
{
myObj obj = new myObj();
// Do something
}
obj is my strong reference to an instance of the class myObj. When I am done with foo and return the flow of control to the function that called foo, it goes out of scope, and the memory allocated for that instance of the class myObj is garbage collected and freed.
As long as an object is reachable via a chain of strong references, it will not be garbage collected.
However there are some issues to consider. Suppose you want to track the number of objects in the program that are currently in play. Or suppose you want to assign serial numbers to instances of a class. Now although these problems can be easily solved by merely extending the classes in question, many a time that is not the case (in case the class is marked as final in Java or sealed in C#). So if you use, say a Hashmap to track the objects, you will have a strong reference to it. So when the object goes dead and should be garbage collected, it won't because of the strong reference to it. So despite the presence of a GC, the programmer will have to worry about when to garbage collect and has to perform manual memory management. Not good.
The solution to this conundrum is a weak reference. Simply put, having a weak reference to an object will not prevent it from being garbage collected. So if the hashmap stores weak references to live objects, once they go dead, you do not have to worry about the garbage collection. However you will have to poll the hashmap to see which objects have died and remove the corresponding weak references. So to save yourself the trouble, use the WeakHashmap generic.
Now what is an AsynTask. Asynchronous tasks in Android, are basically thread-like in their behaviour with a few key differences, they do not require you to worry about the complexities of threading and handlers, but you can call them ONLY from the UI thread. So you can perform background operations in the AsyncTask and then publish the result on the UI without holding up the UI thread.
A WeakAsyncTask allows you to perform asynchronous tasks on objects with weak references. Why is it required? Suppose you launch an AsyncTask , show a nice progress dialog while the AsyncTask is running, and have the progress result be posted back to your UI.
But what happens if the phone rings? Or you rotate your display? Your activity be terminated with extreme prejudice. But AsyncTask will continue to hold a stale reference to the object you created earlier, and although you cannot access it, the strong reference to that object within the AsyncTask will prevent it from being garbage collected. Also the result of the AsyncTask would have been posted to the original instance of your activity, but because it will have been restarted, AsyncTask will not post to this new instance and be effectively floating about in limbo. What we have here is essentially a memory leak.
This is where the WeakAsyncTask comes in. Since it has a weak reference to the target object, when the object is garbage collected, the WeakAsyncTask knows the target object has gone out of scope and will automatically terminate itself, thus solving the issue of memory leaks. This is a pretty useful class and I think it should be a part of the primary Android API.
Wednesday, February 3, 2010
Subscribe to:
Post Comments (Atom)
2 comments:
Excellent description, but do you have an example of this in use? This is exactly the problem my application is experiencing at the moment.
Post a Comment