Reputation: 1794
I am using Retrofit-2.0.0
for my app. Now every tutorial on Retrofit I found on web is based on earlier Retrofit
and there was no Call<T>
interface there. This is the first time I am using Retrofit and I am repeatedly getting null object reference
. Here is my network model interface
public interface TMovieDBService {
@GET("/movie")
Call<MovieResponse> getMovieResponse(@Query("sort_by") String sortKey,
@Query("api_key") String apiKey);
}
And this is my updateMovies()
function which updates the list of movies.
void updateMovies() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://api.themoviedb.org/3/discover")
.addConverterFactory(GsonConverterFactory.create())
.build();
String sortKey = "popularity.desc";
TMovieDBService service = retrofit.create(TMovieDBService.class);
Call<MovieResponse> call = service.getMovieResponse(sortKey, ApiKey.API_KEY);
call.enqueue(new Callback<MovieResponse>() {
@Override
public void onResponse(Response<MovieResponse> response) {
Log.d(LOG_TAG, "Reached this place");
if (!response.isSuccess()) {
Log.d(LOG_TAG, "No Success");
}
mMovieList = response.body().getMovies(); // <- response is null here
// Log.d(LOG_TAG, "Couldn't not reach this place");
mMovieAdapter.notifyDataSetChanged();
Log.d(LOG_TAG, "Response returned by website is : " + response.code());
}
@Override
public void onFailure(Throwable t) {
// Toast for the moment
// Appropriate error handling code should be present here
Toast.makeText(getActivity(), "Failed !", Toast.LENGTH_LONG).show();
}
});
}
I don't know what to implement in the enqueue function. Very little is given on the retrofit website on how to use the callback. Assume all the other code is working fine. Here MovieResponse
object is returned by the movieDB API which contains an array of Movie
s and some extra information. I am implementing it in such a way so that once I get the response in MovieResponse
from there I can extract using the getMovies()
which will return a list of movies.
When I run I simply get null object reference
because response
is null. I tried to search for tutorials on using new Retrofit-2.0.0
especially on using enqueue function but I am out of luck. Plus one more question where should the updateMovies()
be called. Can I call it directly in the mainactivity. Does retrofit automatically run the network call on background thread ?
Upvotes: 19
Views: 68143
Reputation: 501
With Retrofit 2, onResponse
is called even if there is a failure. You have checked whether response is not successful by using !response.isSuccess()
. But you just logged it - if it's true (i.e. not successful). Instead, you could log response.errorBody().string()
to see if api server specifies the error, and you should call something like return
to exit onResponse
callback, as response.body()
couldn't be casted to MovieResponse
, hence the null exception.
By the way, your code is correct, but if you just start with Retrofit, it would be simpler to use 1.9 version as 2.0 is still a beta version (very stable though, but lack of tutorials).
Upvotes: 19
Reputation: 4108
Use an Interceptor from OkHttp On Retrofit 1.9 you could use RequestInterceptor to intercept a Request but it is already removed on Retrofit 2.0 since the HTTP connection layer has been moved to OkHttp.
As a result, we have to switch to an Interceptor from OkHttp from now on. First you have to add it to build.gradle
compile 'com.squareup.okhttp:okhttp:2.5.0'
and then create a OkHttpClient object with an Interceptor like this:
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
// Do anything with response here
return response;
}
});
And then pass the created client into Retrofit's Builder chain.
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://api.themoviedb.org/3/discover/").addConverterFactory(GsonConverterFactory.create()).client(client).build();
Remove '/' from your @GET("/abc") because Retrofit 2.0 comes with new URL resolving concept. Base URL and @Url have not just simply been combined together but have been resolved the same way as what does instead. Please take a look for the examples below for the clarification.
To know more about Retrofit 2.0
Upvotes: 8
Reputation: 772
@AbKDs, I don't know if you already solved it, but I found out after some struggle with retrofit 2 that you need to put "http://api.themoviedb.org" as your baseUrl and add the whole path in @GET. Like so: @GET("/3/discover/movie") And then you add your queries as params for your interface Call.
Upvotes: 2