问题
please help with Retrofit2. I'm very new in Retrofit. I create simple server application. The application manage list of Journals: add Journal in the in-memory list and return Journal by id. There is an Journal.java:
public class Journal {
private AtomicInteger getNewId = new AtomicInteger(0);
@SerializedName("id")
@Expose
private Integer id;
@SerializedName("name")
@Expose
private String name;
public Journal(String name) {
this.id = getNewId.incrementAndGet();
this.name = name;}
public Integer getId() {return id;}
public String getName() {return name;}
}
There is an controller interface:
public interface JournalController {
@GET("journal")
Call<List<Journal>> getJournalList();
@GET("journal/{id}")
Call<Journal> getJournal(@Path("id") Integer id);
@POST("journal")
Call<Journal> addJournal(@Body Journal journal);
}
This is interface implementation:
@Controller
public class JournalControllerImpl implements JournalController {
// An in-memory list that the controller uses to store the Journals
private List<Journal> journals = new ArrayList<>();
@RequestMapping(value= "journal", method=RequestMethod.GET)
public @ResponseBody Call<List<Journal>> getJournalList() {
return (Call<List<Journal>>) journals;}
@RequestMapping(value= "journal/{id}", method= RequestMethod.GET)
public @ResponseBody Call<Journal> getJournal(@Path("id") Integer id) {
Journal journal = journals.get(id);
return (Call<Journal>) journal;}
@RequestMapping(value= "journal", method= RequestMethod.POST)
public @ResponseBody Call<Journal> addJournal(@Body Journal journal) {
journals.add(journal);
return (Call<Journal> ) journal; }
}
The application started succesesully. Console output during application's startup:
Mapped "{[/journal],methods=[GET]}" onto public retrofit2.Call> main.JournalControllerImpl.getJournalList()
Mapped "{[/journal],methods=[POST]}" onto public retrofit2.Call main.JournalControllerImpl.addJournal(main.Journal)
Mapped "{[/journal{/id}],methods=[GET]}" onto public retrofit2.Call main.JournalControllerImpl.getJournal(java.lang.Integer)
Than I try to run URL http://localhost:8080/journal on browser (or GET HttpRequest http://localhost:8080/journal). There is an error in application output:
"... java.lang.ClassCastException: java.util.ArrayList cannot be cast to retrofit2.Call..."
Could you guess what is wrong? Is it really problems with conversion java.util.ArrayList to Call ? (I've tryed to CopyOnWriteArrayList but this doesn't help.
Thank you in advance.
回答1:
Call<T>
is a Retrofit class that only needs to exist on the clientside, it is meant to be an abstraction over a potential call to an external API.
I'm not sure what kind of library you are using for the server but you cannot cast completely unrelated classes. (Such as ArrayList<T>
to Call<List<T>>
)
Usually the library will handle serialization for you, so on the server side you would just directly return the object that you want to send:
@RequestMapping(value= "journal", method=RequestMethod.GET)
public @ResponseBody List<Journal> getJournalList() {
return journals;}
回答2:
The problem has been resolved when the Call been removed from the JournalController (and implementation class JournalControllerImpl). Now JournalController looks like:
public interface JournalController {
String URL_PATH = "journal";
@GET(URL_PATH)
List<Journal> getJournalList();
@GET(URL_PATH +"/{id}")
Journal getJournal(@Path("id") Integer id);
@POST(URL_PATH)
Journal addJournal(@Body Journal journal);
}
And works perfectly.
回答3:
The way to use the service interface (service) is to the service with a callback (onResponse, onFailure)implement the detail the logic need as highlighted below.
//Pass in a constructor upon creating JournalController journalService; //Return journal list
Call<List<Journal>> call = journalService.getJournalList();
call.enqueue(new Callback<>() {
@Override
public void onResponse(Call<List<Journal>> call, Response<List<Journal>>
response) {
int statusCode = response.code();
List<Journal> journal = response.body();
}
@Override
public void onFailure(Call<Journal> call, Throwable t) {
// Log error here since request failed
}
});
//Return a journal
Call<Journal> call = journalService.getJournal(userId);
call.enqueue(new Callback<Journal>() {
@Override
public void onResponse(Call<Journal> call, Response<Journal> response) {
int statusCode = response.code();
Journal journal = response.body();
}
@Override
public void onFailure(Call<Journal> call, Throwable t) {
// Log error here since request failed
}
});
//Add journal
Call<Journal> call = journalService.addJournal(new Journal("username");
call.enqueue(new Callback<Journal>() {
@Override
public void onResponse(Call<Journal> call, Response<Journal> response) {
int statusCode = response.code();
Journal journal = response.body();
}
@Override
public void onFailure(Call<Journal> call, Throwable t) {
// Log error here since request failed
}
});
来源:https://stackoverflow.com/questions/38940610/retrofit2-classcastexception-java-util-arraylist-cannot-be-cast-to-retrofit2-c