我正在为我的应用使用Retrofit-2.0.0
。现在,我在Web上找到的每个Retrofit教程都基于早期的Retrofit
,并且那里没有Call<T>
接口。这是我第一次使用Retrofit而且我一再得到null object reference
。这是我的网络模型界面
public interface TMovieDBService {
@GET("/movie")
Call<MovieResponse> getMovieResponse(@Query("sort_by") String sortKey,
@Query("api_key") String apiKey);
}
这是我的updateMovies()
功能,用于更新电影列表。
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();
}
});
}
我不知道在enqueue函数中要实现什么。关于如何使用回调的改造网站上给出的很少。假设所有其他代码都正常工作。这里的MovieResponse
对象由movieDB API返回,其中包含Movie
的数组和一些额外信息。我正在以这样的方式实现它,以便一旦我从那里得到MovieResponse
中的响应,我就可以使用getMovies()
来提取,这将返回电影列表。
当我跑步时,我只需获得null object reference
,因为response
为空。我试图搜索有关使用新Retrofit-2.0.0
的教程,特别是在使用enqueue函数时,但我运气不好。还有一个问题,应该在哪里调用updateMovies()
。我可以直接在mainactivity中调用它。改造是否会在后台线程上自动运行网络调用?
答案 0 :(得分:15)
使用Retrofit 2,即使出现故障,也会调用onResponse
。您已使用!response.isSuccess()
检查了响应是否成功。但你只是记录它 - 如果它是真的(即不成功)。相反,您可以记录response.errorBody().string()
以查看api服务器是否指定了错误,您应该调用return
之类的内容来退出onResponse
回调,因为response.body()
无法解决被转换为MovieResponse
,因此为空例外。
顺便说一句,你的代码是正确的,但是如果你刚开始使用Retrofit,那么使用1.9版本会更简单,因为2.0仍然是测试版本(尽管非常稳定,但缺乏教程)。
答案 1 :(得分:5)
使用来自OkHttp的Interceptor On Retrofit 1.9你可以使用RequestInterceptor拦截一个Request,但是由于HTTP连接层已被移动到OkHttp,它已经在Retrofit 2.0上删除了。
因此,从现在开始,我们必须从OkHttp切换到Interceptor。 首先,您必须将其添加到 build.gradle
compile 'com.squareup.okhttp:okhttp:2.5.0'
然后用这样的Interceptor创建一个OkHttpClient对象:
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;
}
});
然后将创建的客户端传递给Retrofit的Builder链。
Retrofit retrofit = new Retrofit.Builder().baseUrl("http://api.themoviedb.org/3/discover/").addConverterFactory(GsonConverterFactory.create()).client(client).build();
从@GET(“/ abc”)中删除“/” 因为Retrofit 2.0带有新的URL解析概念。基本URL和@Url不仅仅是简单地组合在一起,而是以与改为相同的方式解决。请查看以下示例以获得澄清。
答案 2 :(得分:0)
@AbKDs,我不知道你是否已经解决了这个问题,但是在经过一些改造之后我发现你需要放置&#34; http://api.themoviedb.org&#34;作为你的baseUrl并在@GET中添加整个路径。像这样:@GET(&#34; / 3 / discover / movie&#34;) 然后将查询添加为接口Call的参数。