在Retrofit

时间:2015-09-07 05:16:01

标签: android retrofit

我正在为我的应用使用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中调用它。改造是否会在后台线程上自动运行网络调用?

3 个答案:

答案 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不仅仅是简单地组合在一起,而是以与改为相同的方式解决。请查看以下示例以获得澄清。

To know more about Retrofit 2.0

答案 2 :(得分:0)

@AbKDs,我不知道你是否已经解决了这个问题,但是在经过一些改造之后我发现你需要放置&#34; http://api.themoviedb.org&#34;作为你的baseUrl并在@GET中添加整个路径。像这样:@GET(&#34; / 3 / discover / movie&#34;) 然后将查询添加为接口Call的参数。