views:

44

answers:

1

I have written a home screen widget as an ImageView, ie. the code generates the whole widget and writes it to RemoteViews as a bitmap. On slower devices with low memory, such as my G1, it can take a couple of seconds to generate the bitmap, and to avoid the dreaded force-close, I moved all the graphics code into an AsyncTask. So far so good.

However, in very low memory conditions, the AsyncTask can easily be killed by the OS before it has finished generating the bitmap, resulting in an empty square on the homescreen. So before creating the AsyncTask, it sets an alarm for now + 5 seconds, and after the graphics are complete, it resets the alarm. The assumption here is that if the alarm is triggered, more than likely the process was killed, and we have to set another now+5 alarm and start again.

This does work, but in extreme low memory conditions it can take several attempts (20+ seconds) to draw the widget, so I added a placeholder hourglass image, as a static resource, which is displayed on the homescreen until the real image is ready.

My question is this: is this the best way? Is there some way to (politely) ask the OS not to kill the AsyncTask until it's finished (on the grounds that killing it will actually result in more waste of system resources)?

I understand that if a process is categorised as "visible" then Android won't kill it except as a last resort. But I don't know how to tag an AsyncTask as "visible". I'm very happy for the process to be killed just as soon as it's done drawing the widget. Would just like it to stay alive long enough to complete.

A: 

Have you considered using an IntentService for this? While your service code is executing it gets the same kill priority as a foreground task. It won't have quite the tight coupling to the widget that an AsyncTask would, but I think it would increase the odds of your code finishing.

Mike
I just tried that, and spent a few hours playing with different settings. I tried it with START_STICKY, with setForeground(), and with acquisition of a WAKE_LOCK. Unfortunately, none of them kept the code alive in low memory situations, nor did they recover as easily and quickly as the alarm code I am currently using.
Andy
I was looking through some of Google's Android OS code and I noticed that when they are using an AsyncTask, they will occasionally start an empty service from within the AsyncTask, and according to the comments it's to keep the task from being killed. You can see a reference to it in this file at line 670: http://android.git.kernel.org/?p=platform/packages/apps/Contacts.git;a=blob;f=src/com/android/contacts/ui/EditContactActivity.java;h=3e248ea93dc8b17a0d66306aaade9ea398c32408;hb=HEAD
Mike