【发布时间】:2020-01-03 09:42:39
【问题描述】:
我正在使用改造对 android 中的 themoviedb.org api 进行 api 调用。我期望响应中有一个包含电影列表的 json 数组,但是当我调用我的 POJO 类的 getResults 方法时,我得到一个空对象引用。请协助。
这是我收到的错误消息;
2020-01-03 12:28:10.396 20851-20851/com.popularmovies E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.popularmovies, PID: 20851
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.gson.JsonArray com.popularmovies.TrendingPojo.getResults()' on a null object reference
at com.popularmovies.TrendingFragment$1.onResponse(TrendingFragment.java:109)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:71)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7045)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)
这是我的api接口
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface TmdbApi {
final String BASE_URL = "https://api.themoviedb.org/4/";
@GET("list/{id}")
Call<CategoryJsonResponse> getMovies(@Path ("id") String id, @Query("api_key") String api_key);
@GET("discover/movie")
Call<DiscoverPOJO> getDiscover(@Query("sort_by") String sort_by,@Query("api_key") String api_key);
@GET("trending/{media_type}/{time_window}")
Call<TrendingPojo> getTrending(@Path("media_type") String media_type, @Path("time_window") String time_window, @Query("api_key") String api_key);
}
我的问题在于趋势端点。
下面是我的 POJO 类
package com.popularmovies;
import com.google.gson.JsonArray;
public class TrendingPojo {
private int page;
private JsonArray results;
private int total_results;
private int total_pages;
//Default constructor for api calls
public TrendingPojo(int page, JsonArray results, int total_pages, int total_results) {
this.page = page;
this.results = results;
this.total_results = total_results;
this.total_pages = total_pages;
}
public int getPage() {
return page;
}
public JsonArray getResults() {
return results;
}
public int getTotal_results() {
return total_results;
}
public int getTotal_pages() {
return total_pages;
}
public void setPage(int page) {
this.page = page;
}
public void setResults(JsonArray results) {
this.results = results;
}
public void setTotal_results(int total_results) {
this.total_results = total_results;
}
public void setTotal_pages(int total_pages) {
this.total_pages = total_pages;
}
}
以下是我使用改造进行 api 调用的片段;
package com.popularmovies;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import static com.popularmovies.DiscoverFragment.API_KEY;
public class TrendingFragment extends Fragment implements MovieAdapter.MovieAdapterOnclickHandler {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private View rootView;
private ProgressBar progressBar;
private RecyclerView mRecyclerView;
private MovieAdapter movieAdapter;
private List<Movies> moviez;
public TrendingFragment() {
// Required empty public constructor
}
// TODO: Rename and change types and number of parameters
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_trending, container, false);
progressBar = rootView.findViewById(R.id.trending_pb);
progressBar.setVisibility(View.VISIBLE);
mRecyclerView = rootView.findViewById(R.id.trending_rv);
GridLayoutManager layoutManager = new GridLayoutManager(rootView.getContext(), 2);
mRecyclerView.setLayoutManager(layoutManager);
mRecyclerView.setHasFixedSize(true);
movieAdapter = new MovieAdapter(this);
mRecyclerView.setAdapter(movieAdapter);
getTrendingResponse();
return rootView;
}
// TODO: Rename method, update argument and hook method into UI event
private void getTrendingResponse(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(TmdbApi.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
TmdbApi tmdbApi = retrofit.create(TmdbApi.class);
Call<TrendingPojo> call = tmdbApi.getTrending("movie","week",API_KEY);
call.enqueue(new Callback<TrendingPojo>() {
@Override
public void onResponse(Call<TrendingPojo> call, Response<TrendingPojo> response) {
TrendingPojo movies = response.body();
JsonArray allmovies;
allmovies = movies.getResults();
if(allmovies!= null){
for(int i = 0; i < allmovies.size(); i++){
Gson gson = new Gson();
Type listType = new TypeToken<Collection<Movies>>(){}.getType();
moviez = gson.fromJson(allmovies, listType);
}
movieAdapter.setData(moviez);
progressBar.setVisibility(View.INVISIBLE);
}
}
@Override
public void onFailure(Call<TrendingPojo> call, Throwable t) {
Toast.makeText(rootView.getContext(), t.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
@Override
public void onDetach() {
super.onDetach();
}
@Override
public void onClick(int s) {
}
}
最后,这里是趋势端点的 api 文档的链接。 https://developers.themoviedb.org/3/trending/get-trending
【问题讨论】:
标签: android retrofit2 themoviedb-api