使用RoboSpice / Retrofit和参数化类型进行JSON响应

时间:2014-09-02 09:17:59

标签: java android json generics retrofit

请帮助T_T挖掘2天以找到解决此问题的方法!

我正在使用Retrofit在我的应用中制作一些网络任务, 我调用的其中一个API有时会返回一个不同的对象,但我知道每次调用它时它将返回什么时候以及它将返回什么。

在这种情况下,Message是一个对象

{
  "key": "some key",
  "category": "some category",
  "channel": "some channel",
  "status": "some status",
  "message": {
    "someValue": "54",
    "someOtherValue": "5353"
  }
}

此处Message是一个字符串

{
  "key": "some key",
  "category": "some category",
  "channel": "some channel",
  "status": "some status",
  "message": "this is a string"
}

所以我试图通过使用泛型来实现这个解决方案的良好设计, 我有一个这样的通用类,

ContentResponse类

public class ContentResponse<T> {

private List<Content<T>> content = new ArrayList<Content<T>>();

//getters and setters
}

内容类

public class Content<T>
{
    private String key;
    private String category;
    private String channel;
    private String status;
    private T message;

    //getters and setters
}

ContentInterface类

public interface ContentInterface<T>
{
    @GET("/public/content/{category}")
    ContentResponse<T> getContent(@Path(PathParameters.CATEGORY) String category);
}

问题出在这里

public class ContentRequest<T> extends RetrofitSpiceRequest<ContentResponse<T>, ContentInterface<T>>
        {
        String category;

        public ContentRequest(Class<ContentResponse<T>> clazz, Class<ContentInterface<T>> retrofittedInterfaceClass, String category) {
            super(clazz, retrofittedInterfaceClass);
            this.category = category;
        }


        @Override
        public ContentResponse<T> loadDataFromNetwork() throws Exception {
            return getService().getContent(category);
        }
    }

在此上下文中,我知道返回的对象是Map<String, String>

    contentRequest = new ContentRequest(new Class<ContentResponse<Map<String, String>>>(),
new Class<ContentInterface<Map<String, String>>>(),
"appstrings");

但是我明白了!

  

'class()'在java.lang.Class

中不公开

我不能打电话给ContentResponse<Map<String,String>>.class,那我该怎么办?

1 个答案:

答案 0 :(得分:4)

这在Retrofit中是不可能的

public interface ContentInterface<T>
{
    @GET("/public/content/{category}")
    ContentResponse<T> getContent(@Path(PathParameters.CATEGORY) String category);
}

Retrofit在运行时使用方法的签名来确定返回Type。在这种情况下,它将是Class的原始ContentResponseParameterizedType T,显然无法正常工作。

使这项工作的方法是在界面中添加ParameterizedType,就像这样。 编辑:注意ContentInterface

不再输入T的方式
public interface ContentInterface
{
    @GET("/public/content/{category}")
    ContentResponse<String> getContent(@Path(PathParameters.CATEGORY) String category);
}

但是那会失败,因为你不能拥有2个具有相同签名的方法定义。由于类型擦除,这不会编译。

public interface ContentInterface
{
    @GET("/public/content/{category}")
    ContentResponse<String> getContent(@Path(PathParameters.CATEGORY) String category);

    ContentResponse<Map<String, String> getContent(@Path(PathParameters.CATEGORY) String category);
}

所以最后你还需要创建2种不同的方法来与2种不同类型的数据进行交互。

public interface ContentInterface
{
    @GET("/public/content/{category}")
    ContentResponse<String> getContentAsString(@Path(PathParameters.CATEGORY) String category);

    ContentResponse<Map<String, String> getContentAsMap(@Path(PathParameters.CATEGORY) String category);
}

请参阅@JakeWharton回复here关于使用Retrofit的概括以及他们为什么不真正支持它。我相信同样的想法适用于此。