Reputation: 2229
I'm using retrofit library to do API calls for my app. I wrote a seperate function for the API so that it is re usable. The response I'm getting back is a list of the object 'Movies' . But im not able to return the object . What should I do here?
The function which gets the data from API
// These are the retrofit codes to get the data from TMDB API
private List<Movies> getDataFromServer(int page)
{
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<Response> call = apiService.getPopularMovies(API_KEY , page);
List<Movies> movies = new ArrayList<>();
call.enqueue(new Callback<Response>() {
@Override
public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
movies = response.body().getMovies();
}
@Override
public void onFailure(Call<Response> call, Throwable t) {
Log.e(TAG,t.toString());
movies = null;
}
});
return movies;
}
It says that I should declare the movies as final but when I do , it automatically converts the array list into an array and the movies inside the onResponse and onFailure is turned into moviess[0]. I just want to get the movies , and then return it as a List
Upvotes: 1
Views: 4239
Reputation: 2162
The problem is that you are calling from onResponse which is a callback method and will take time to load data and come and load them in your movies list.You will never know when the response will be receiver , therefore taking a return is not a good idea.You should continue whatever you are doing from inside of onResponse().
@Override
public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
if (response.isSuccessful()) {
movies = response.body().getMovies();
//continue whatever you want do from here when the response is received.
}
}
Upvotes: 1
Reputation: 1086
i think you are using android studio's features to change the modifier to final but it does not work as you wish and changing the movies modifier ti final wont fix your problem because you fetch data in another thread and you just return null.you can declare a method to call when you fetched data then do what ever you want with it
//declare movies as a class field
List<Movies> movies;
...
private List<Movies> getDataFromServer(int page)
{
...
call.enqueue(new Callback<Response>() {
@Override
public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
dataIsReady(response.body().getMovies();
}
@Override
public void onFailure(Call<Response> call, Throwable t) {
Log.e(TAG,t.toString());
movies = null;
}
});
}
private void dataIsReady(List<Movies> movies){
this.movies = movies;
//do what you want with movies
}
Upvotes: 0
Reputation: 2257
You can declare your movies list as a field in your class and then write something like this :
private List<Movies> getDataFromServer(int page)
{
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<Response> call = apiService.getPopularMovies(API_KEY , page);
call.enqueue(new Callback<Response>() {
@Override
public void onResponse(Call<Response> call, retrofit2.Response<Response> response) {
if (response.isSuccessful()) {
movies = response.body().getMovies(); }
else{
//show error
}
}
@Override
public void onFailure(Call<Response> call, Throwable t) {
Log.e(TAG,t.toString());
movies = null;
}
});
return movies;
}
also remember to check that your response is Successful.
Upvotes: 1