skabo
skabo

Reputation: 71

AsyncTask without callback interface

I'm trying to resolve this problem: I have a class that extends from AsyncTask, that execute some http methods, something like this:

    public class RESTManager extends AsyncTask<Object, Object, String>
{
    public RESTManager(String url, MethodTypes myMethod,ICallbackHandler hndl, String     restMethod)
    {
        initialize();
    }

    private String doGET()
    {
    }

    private String doPOST()
    {
    }

    @Override
    protected String doInBackground(Object... params)
    {

    }

    @Override
    protected void onPostExecute(String result)
    {
    }

}

So, from Activity I' doing this:

RESTManager webService = new WSManager(URL, MethodTypes.REGISTER, params, this, WSManager.GET_METHOD);
webService.execute();

And then the activity receives the response in the callbak method (because activity implements this interface):

public void response(String response)
{
    // some process
}

This is working ok, but my problem is that I would like that the answer comes in the same call to some function, and then that function calls the .execute method, for example.

// This is a new class
public class MyWebServices()
{
    public User getUser(int id)
    {
        User myUser;

        RESTManager webService = new WSManager(URL, MethodTypes.REGISTER, params, this, WSManager.GET_METHOD);
        webService.execute();

        // BUT I WANT TO RETURN FROM HERE THE CALL FROM THE ACTIVITY....LIKE

        return myUser;
    }
}

So from the activity this will be:

MyWebServices myService = new MyWebServices();
User usr = myService.getUser(id);

Hope undestand what I tried to describe, thanks!

Upvotes: 0

Views: 1115

Answers (2)

Jeffrey Blattman
Jeffrey Blattman

Reputation: 22637

learn to love callbacks :)

you cannot apply the pattern you mention (do in background, wait for result, return value) without blocking the UI thread.

the simplest thing is to simply implement the onPostExecute() method to call the thing you want to do after the REST call completes. you can however get more sophisticated, if you want to expose a clean interface to other parts of the system.

start by reading about the observer pattern. think of it this way: the completion of your REST call is an event, and code that is interested in that event can register to be notified (asynchronously) when it completes. you could do this my making your AsyncTask impl something like this,

AsyncTask myTask = new AsyncTask<...>() {
    public interface Callback {
        void onComplete();
        void onFailure();
    }

    private Set<Callback> callbacks = new HashSet<Callback>();

    public void addObserver(Callback cb) { callbacks.add(cb); }

    @Override
    protected String doInBackground(Object... params)
    {
        // whatever
    }

    @Override
    protected void onPostExecute(String result)
    {
        if (success) {
            for (Callback cb: callbacks) {
                cb.onComplete();
            }
        } else {
            for (Callback cb: callbacks) {
                cb.onFailure();
            }       
        }
    }
}

now, the consumer of this interface does something like,

MyTask mt = new MyTask();
mt.addObserver(new MyTask.Callback() { 
    @Override
    public void onComplete() {
        // do whatever you want to do when the task completes successfully
    }

    @Override
    public void onFailure() {
        // ...
    }
}

mt.execute();

Upvotes: 1

Vladimir Ivanov
Vladimir Ivanov

Reputation: 43098

What you want leads to blocking UI. Android doesn't allow you to do that. Network calls SHOULD be asynchronous, so the approach is wrong. Deal with response() method.

UPD: Blocking UI leads to "Application not responsive dialog" which annoys users. Also, what if the network call fails? Or it waits for half an hour to complete?

Upvotes: 1

Related Questions