Frage

I'm developing an Android app which has a lot of different requests for web services. Every request is done in a subclass of AsyncTask in this manner:

(new AsyncTask<String, Void, Object1>() {
    @Override
    protected Object1 doInBackground(String... params) {
        // network request and parsing to Object1
        Object1 obj = new Object1();
        obj1 = Parser.parseObject1(httpClient.execute(...));
        return obj1;
    }

    @Override
    protected Object1 onPostExecute(Object1... ret) {
        return ret[0];
    }
}).execute();

Object1 is a placeholder for different objects (Car, Bicycle, Truck...), each one in a different AsyncTask.

What are my alternatives other than returning the output of httpClient in a String and parsing in the Main Thread (UI Thread)? Avoid parsing in the UI Thread sounds reasonable if it's going to parse a lot of data, am I right?

-= UPDATE =-

Let me rephrase the question: I'm asking for a more intelligent way to develop my application avoiding being repetitive (AsyncTask has a lot of boilerplate code). The way I did was by creating 20+ subclasses of AsyncTask, which clearly is not DRY (do not repeat yourself).

In iOS we have lambda expressions so callbacks done in web requests are very easy and succinct.

War es hilfreich?

Lösung

You can create classes that contain most of your boilerplate code. E.g.

public class SpecialAsyncTask<T> extends AsyncTask<String, Void, T> {

    public interface ResultProvider<T> {
        T generateResultInBackground(String... params);
    }

    public interface ResultConsumer<T> {
        void handleResultInForeground(T result);
    }

    private final ResultProvider<T> mProvider;
    private final ResultConsumer<T> mConsumer;
    private SpecialAsyncTask(ResultProvider<T> provider, ResultConsumer<T> consumer) {
        mProvider = provider;
        mConsumer = consumer;
    }

    @Override
    protected T doInBackground(String... params) {
        return mProvider.generateResultInBackground(params);
    }

    @Override
    protected void onPostExecute(T result) {
        mConsumer.handleResultInForeground(result);
    }

    public static <T> void execute(ResultProvider<T> provider, ResultConsumer<T> consumer, String... params) {
        new SpecialAsyncTask<T>(provider, consumer).execute(params);
    }
}

is an example how you could keep Object1 as a generic parameter while being able to specify an object that only needs to implement an interface to handle code that would otherwise have to be inside a new AsyncTask instance.

With a schema like that you could for example define some common code as static content:

class Providers {
    public static final ResultProvider<String> HTTP_GETTER = new ResultProvider<String>() {

        @Override
        public String generateResultInBackground(String... params) {
            return MagicHttpLibrary.getContentAsString(params[0]);
        }

    };
}

And you can just use Providers.HTTP_GETTER as parameter instead of implementing doInBackground. Or create a new class hierarchy of that implement one of those interfaces with different methods to access them (like factories for example)

Use of above example would look for example like below

class User extends Activity implements ResultConsumer<String> {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        SpecialAsyncTask.execute(Providers.HTTP_GETTER, this , "http://google.com");
        SpecialAsyncTask.execute(Providers.HTTP_GETTER, this , "http://yahoo.com");
    }

    @Override
    public void handleResultInForeground(String result) {
        Toast.makeText(this, result, Toast.LENGTH_LONG).show();
    }
}

and there is more or less no repeated code besides the different method calls. It depends on how you want to use a class and what actually changes in the code to know how to design something like that. Identify the parts that need to be parametrized and move code that repeats into a re-used place (inheritance / composition).

Andere Tipps

Google's Volley HTTP request library does the request and parsing both in the same worker thread. So, that's a pretty good example to code by.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top