views:

168

answers:

1

I have a Service that creates AsyncTasks for downloading files. In activities, we create Runnables or Threads that we pass to Activity.runOnUiThread(). I can't access that method from a service, so how do I use AsyncTask correctly, (do heavy work without blocking the UI Thread)?

A: 

If your service is only called from your application, and you can make it a singleton, then try this:

public class FileDownloaderService extends Service implements FileDownloader {
    private static FileDownloaderService instance;

    public FileDownloaderService () {
        if (instance != null) {
            throw new IllegalStateException("This service is supposed to be a singleton");
        }
    }

    public static FileDownloaderService getInstance() {
        // TODO: Make sure instance is not null!
        return instance;
    }

    @Override
    public void onCreate() {
        instance = this;
    }

    @Override
    public IBinder onBind(@SuppressWarnings("unused") Intent intent) {
        return null;
    }

    @Override
    public void downloadFile(URL from, File to, ProgressListener progressListener) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // Perform the file download
            }
        }).start();
    }
}

Now you can directly call methods on your service. So just call downloadFile() to put the service to work.

About your real question of how to update the UI. Notice that this method receives a ProgressListener instance. It could look like this:

public interface ProgressListener {
    void startDownloading();
    void downloadProgress(int progress);
    void endOfDownload();
    void downloadFailed();
}

Now you just update the UI from the activity (not from the service, which remains unaware of how the UI looks like).

espinchi