Search code examples
javaandroidgenericsandroid-ion

Java generic method type argument


I have a problem with generic method's explicit type arguments. I know I can do this:

Foo.<Bar>function();

assuming there is a

void <T> function() {...}

function in Foo class. The exact problem is:

  • I would like to download some content (Android with Ion)

  • These contents are similar (Article, BlogArticle, ...), all implements a ContentItem interface

  • At the moment the downloading looks like this:

news for example

private void downloadNews() {
    Ion.with(this)
    .load(URL_NEWS)
    .as(new TypeToken<List<Article>>(){})
    .setCallback(new FutureCallback<List<Article>>() {
        @Override
        public void onCompleted(Exception e, List<Article> result) {
            // do something with result
        }
    });
}

If I want to download blog articles, I have to change url and Article class only (for BlogArticle).

I tried to make a generic function like this:

private <T extends ContentItem> void download(String url) {
    Ion.with(this)
    .load(url)
    .as(new TypeToken<List<T>>(){})
    .setCallback(new FutureCallback<List<T>>() {
        @Override
        public void onCompleted(Exception e, List<T> result) {
            // do something with result
        }
    });
}

and call that function

this.<Article>download(url);

It's ok, compile fine. After running I get

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.my.packagename.model.ContentItem

The problem is that it doesn't use the explicit class for mapping Json to pojo.

Can you suggest me a generic solution?


Solution

  • Years later, but I thought it can be useful for someone. I ended up with a simpler solution. It's just a simple, truncated version but you can get the idea:

    public static <T> void asList(Context context, String url, Class<T[]> clazz, final FutureCallback<List<T>> callback) {
        Ion.with(context)
            .load(url)
            .as(clazz)
            .setCallback(new FutureCallback<T[]>() {
                @Override
                    public void onCompleted(Exception e, T[] result) {
                        callback.onCompleted(e, Arrays.asList(result));
                    }
            });
    }
    

    And use like:

    asList(context, url, YourObject[].class, new FutureCallback<List<YourObject>>() {...});