2014-09-02 30 views
2

请帮助T_T一直在挖掘2天以解决此问题!使用RoboSpice/Retrofit与参数化类型进行JSON响应

我正在使用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"); 

,但我得到这个!

'类()不是公共java.lang.Class中

我不能只是叫ContentResponse<Map<String,String>>.class,所以我能在这里做?

回答

3

这是不可能的改造

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

改造使用方法的签名在运行时确定返回Type。在这种情况下,它将是一个ClassContentResponseParameterizedTypeT,这显然不起作用。

使这项工作的方法是像这样在界面中添加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关于与改造泛化,为什么他们并不真正支持它。我相信相同的想法适用于此。

+0

感谢您的非常详细的答案:) 所以我会为每种类型的响应创建多个方法,但是如何获取ContentRequest的参数化'ContentResponse'类型? – 2014-09-03 19:42:21

+0

由于ContentInterface接口不再使用'T'类型,因此您只需传递ContentInterface.class即可。 'contentRequest =新ContentRequest(/ *不知道这是怎么使用*/ContentInterface.class, “appstrings”);' – 2014-09-03 19:54:40

+0

你是对的,但ContentRequest取2个PARAMS(类的responseType,类 retrofitInterface) ,第一个参数是预期的响应类型,我期望ContentResponse >时应该传递什么? – 2014-09-03 20:42:55