开发者

Java generics on an Android AsyncTask

For an Android project I have a number of response tasks that I want to run async. The tasks differ only by the type of class that they produce. I'm new to Java generics, so I'm having a difficult time开发者_开发问答 replacing the News.class with a generic T or ClassT (still working out the differences) could someone point out how I can factor this correctly?

private class AcquireResponseTask<T> extends AsyncTask<RestClient, Void, T> 
{
     protected void onPostExecute(T news) 
     {
         process(news);
     }

    @Override
    protected T doInBackground(RestClient... rc)
    {

        return (T) DataToObject.acquireResponse(rc[0],
                News.class);
    }
 }


So here's the process that seems to work. For any request I have where the response will be JSON data where I want the data to be both retrieved and parsed by GSON into a Java class object - create a new AcquireResponseTask of type "the JSON data represented as a Java class" with the class type and processing function object to handle the concrete details.

public interface ProcessResponse<T>
{
    void process(T response);
}

public class AcquireResponseTask<T> extends AsyncTask<RestClient, Void, T> 
{
    private Class<T> type;
    private ProcessResponse<T> func;

    public AcquireResponseTask(Class<T> classType, ProcessResponse<T> f)
    {
        type = classType;
        func = f;
    }

     protected void onPostExecute(T response) 
     {
         func.process(response);
     }

    @Override
    protected T doInBackground(RestClient... rc)
    {
        return (T) JSONToJava.acquireResponse(rc[0],
                type);
    }
 }  

Rather than write the above code multiple times for each data type, I now provide the following code for each:

class TopicsResponseProcessor implements ProcessResponse<Topics>
    {
        public void process(Topics response)
        {
            createTopicsList(response);
        }

    }

new AcquireResponseTask<Topics>(Topics.class,TopicsResponseProcessor ()).execute(UrlBuilder.getTopics());


One thing you need to remember when working with generics, is that the type information is present only at compile time, not runtime. If you need to do runtime stuff with the type (like your cast to T), then you need to explicitly have the Class object for that type around.

So you could pass in the class in your Constructor, then use it later to do your cast:

private final Class<T> theTClass;

public AcquireResponseTask( Class<T> clazz ) {
    theTClass = clazz;
}

@Override
protected T doInBackground(RestClient... rc)
{

    return theTClass.cast( DataToObject.acquireResponse(rc[0],
            News.class));
}


What do you return from:

return (T) DataToObject.acquireResponse(rc[0],
                News.class);

It's a News object?

If it is, then:

private class AcquireResponseTask extends AsyncTask<RestClient, Void, News> 
{

@Override
protected News doInBackground(RestClient... rc)
{

    return (News) DataToObject.acquireResponse(rc[0],
            News.class);
}

@Override
protected void onPostExecute(News news) 
 {
     process(news);
 }

}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜