【发布时间】:2019-07-03 03:28:58
【问题描述】:
我有这样的 json 响应。
{
"movies": [
{
"Title": "Avengers:Age of Ultron ",
"Year": "2015 ",
"Rated": "PG-13 ",
"Released": "01 May 2015 ",
"Runtime": "141 min ",
"Genre": "Action, Adventure, Sci-Fi ",
"Director": "Joss Whedon ",
"Writer": "Joss Whedon, Stan Lee (based on the Marvel comics by), Jack Kirby (based on the Marvel comics by), Joe Simon (character created by: Captain America), Jack Kirby (character created by: Captain America), Jim Starlin (character created by: Thanos) ",
"Actors": "Robert Downey Jr., Chris Hemsworth, Mark Ruffalo, Chris Evans ",
"Plot": "When Tony Stark and Bruce Banner try to jump-start a dormant peacekeeping program called Ultron, things go horribly wrong and it's up to Earth's mightiest heroes to stop the villainous Ultron from enacting his terrible plan. ",
"Language": "English, Korean ",
"Country": "USA ",
"Awards": "7 wins \u0026 45 nominations."
},
{
"Title": "TheAvengers ",
"Year": "2012 ",
"Rated": "PG-13 ",
"Genre": "Action, Adventure, Sci-Fi ",
"Actors": "Robert Downey Jr., Chris Evans, Mark Ruffalo, Chris Hemsworth ",
"Plot": "Earth's mightiest heroes must come together and learn to fight as a team if they are going to stop the mischievous Loki and his alien army from enslaving humanity. ",
"Language": "English, Russian, Hindi ",
"Country": "USA ",
**"Poster": "https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_SX300.jpg ",**
"Released": "04 May 2012 ",
"Runtime": "143 min ",
"Director": "Joss Whedon ",
"Writer": "Joss Whedon (screenplay), Zak Penn (story), Joss Whedon (story) ",
"Awards": "Nominated for 1 Oscar. Another 38 wins \u0026 79 nominations. "
},
{
"Title": "Sleepless ",
"Year": "2017 ",
"Rated": "R ",
"Released": "13Jan 2017 ",
"Runtime": "95 min ",
"Genre": "Action, Crime, Thriller ",
"Director": "Baran bo Odar ",
"Writer": "Andrea Berloff (screenplay by), Frédéric Jardin (based on the film Nuit blanche written by), Nicolas Saada (based on the film Nuit blanche written by), Olivier Douyère (based on the film Nuit blanche written by)",
"Actors": "Jamie Foxx, Michelle Monaghan, Scoot McNairy, Dermot Mulroney ",
"Plot": "A cop with a connection to the criminal underworld scours a nightclub in search of his kidnapped son. ",
"Language": "English ",
"Country": "USA ",
"Awards": "1 nomination. ",
**"Poster ": "https://m.media-amazon.com/images/M/MV5BNjEwMDAyOTM4OV5BMl5BanBnXkFtZTgwMzc4MjMyMDI@._V1_SX300.jpg "**
},
{
"Title": "TheDark Knight ",
"Year": "2008 ",
"Rated": "PG-13 ",
"Released": "18 Jul 2008 ",
"Runtime": "152 min ",
"Genre": "Action, Crime, Drama ",
"Director": "Christopher Nolan ",
"Writer": "Jonathan Nolan (screenplay), Christopher Nolan (screenplay), Christopher Nolan (story), David S. Goyer (story), Bob Kane (characters) ",
"Actors": "Christian Bale, Heath Ledger, Aaron Eckhart, Michael Caine ",
"Plot": "When the menace known as the Joker emerges from his mysterious past, he wreaks havoc and chaos on the people of Gotham. The Dark Knight must accept one of the greatest psychological and physical tests of his ability to fight injustice. ",
"Language": "English, Mandarin ",
"Country": "USA, UK ",
"Awards": "Won 2 Oscars. Another 152 wins \u0026 155 nominations. ",
**"Poster ": "https://m.media-amazon.com/images/M/MV5BMTMxNTMwODM0NF5BMl5BanBnXkFtZTcwODAyMTk2Mw@@._V1_SX300.jpg "**
},
{
"Title": "SavingPrivate Ryan ",
"Year": "1998 ",
"Rated": "R ",
"Released": "24 Jul 1998 ",
"Runtime": "169 min ",
"Genre": "Drama, War ",
"Director": "Steven Spielberg ",
"Writer": "Robert Rodat ",
"Actors": "Tom Hanks, Tom Sizemore, Edward Burns, Barry Pepper ",
"Plot": "Following the Normandy Landings, a group of U.S. soldiers go behind enemy lines to retrieve a paratrooper whose brothers have been killed in action. ",
"Language": "English, French, German, Czech ",
"Country": "USA ",
"Awards": "Won 5 Oscars. Another 74 wins \u0026 74 nominations. ",
**"Poster ": "https://m.media-amazon.com/images/M/MV5BZjhkMDM4MWItZTVjOC00ZDRhLThmYTAtM2I5NzBmNmNlMzI1XkEyXkFqcGdeQXVyNDYyMDk5MTU@._V1_SX300.jpg "**
},
{
"Plot": "Moirac, a notary, and Landron, a retired army surgeon, who have been friends since boyhood, live in the same village. The daughter of the notary is, at the same time, the god-child of the...",
"Title": "Fatherand God Father ",
"Year": "1912 ",
"Rated": "N/A ",
"Released": "27 Feb 1913 ",
"Runtime": "N/A ",
"Genre": "Short, Comedy ",
"Director": "N/A ",
"Writer": "N/A ",
"Actors": "N/A ",
"Language": "French ",
"Country": "France ",
"Awards": "N/A ",
**"Poster ": "N/A ",**
"Ratings ": "",
"Metascore ": "N/A ",
"imdbRating ": "N/A ",
"imdbVotes ": "N/A ",
"imdbID ": "tt1318958 ",
"Type ": "movie ",
"DVD ": "N/A ",
"BoxOffice ": "N/A ",
"Production ": "N/A ",
"Website ": "N/A ",
"Response ": "True "
}
在上面的 json 响应中,您可以看到“Poster” json 键不存在于第一个数据集中,而它存在于第二个数据集中,类似地,对于某些数据集它为 null。
现在的问题是,当我在 Retrofit 中使用时,只有一个来自 Poster 的数据,它返回,而对于所有其他数据,它显示为 null 问题仅针对 Poster
下面是我的课程。
public class Movies {
@SerializedName("Released")
private String Released;
@SerializedName("Plot")
private String Plot;
@SerializedName("Director")
private String Director;
@SerializedName("Title")
private String Title;
@SerializedName("Actors")
private String Actors;
@SerializedName("Runtime")
private String Runtime;
@SerializedName("Awards")
private String Awards;
@SerializedName("Year")
private String Year;
@SerializedName("Language")
private String Language;
@SerializedName("Rated")
private String Rated;
@SerializedName("Country")
private String Country;
@SerializedName("Genre")
private String Genre;
@SerializedName("Writer")
private String Writer;
@SerializedName("Poster")
@Expose
private String Poster;
public String getPoster() {
return Poster;
}
public void setPoster(String Poster) {
this.Poster = Poster;
}
public String getReleased() {
return Released;
}
public void setReleased(String Released) {
this.Released = Released;
}
public String getPlot() {
return Plot;
}
public void setPlot(String Plot) {
this.Plot = Plot;
}
public String getDirector() {
return Director;
}
public void setDirector(String Director) {
this.Director = Director;
}
public String getTitle() {
return Title;
}
public void setTitle(String Title) {
this.Title = Title;
}
public String getActors() {
return Actors;
}
public void setActors(String Actors) {
this.Actors = Actors;
}
public String getRuntime() {
return Runtime;
}
public void setRuntime(String Runtime) {
this.Runtime = Runtime;
}
public String getAwards() {
return Awards;
}
public void setAwards(String Awards) {
this.Awards = Awards;
}
public String getYear() {
return Year;
}
public void setYear(String Year) {
this.Year = Year;
}
public String getLanguage() {
return Language;
}
public void setLanguage(String Language) {
this.Language = Language;
}
public String getRated() {
return Rated;
}
public void setRated(String Rated) {
this.Rated = Rated;
}
public String getCountry() {
return Country;
}
public void setCountry(String Country) {
this.Country = Country;
}
public String getGenre() {
return Genre;
}
public void setGenre(String Genre) {
this.Genre = Genre;
}
public String getWriter() {
return Writer;
}
public void setWriter(String Writer) {
this.Writer = Writer;
}
以上是我为海报指定为 SerializedName 的 pojo 类。
现在在改造中,
public class MoviesRepository {
private static MoviesRepository moviesRepository;
private MovieApiInterface newsApi;
public static Application application;
public static MoviesRepository getInstance() {
if (moviesRepository == null) {
moviesRepository = new MoviesRepository(application);
}
return moviesRepository;
}
public MoviesRepository(Application application) {
this.application = application;
newsApi = RetrofitService.cteateService(MovieApiInterface.class);
}
public MutableLiveData<MovieResponse> getMovieUpdates() {
final MutableLiveData<MovieResponse> moviesData = new MutableLiveData<>();
newsApi.getMovieDetails().enqueue(new Callback<MovieResponse>() {
@Override
public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
if (response.isSuccessful()) {
if(response.body()!=null) {
moviesData.setValue(response.body());
}
}
}
@Override
public void onFailure(Call<MovieResponse> call, Throwable t) {
Log.i("RETROFIT RESPONSE", "Failure"+call.toString());
Log.i("RETROFIT RESPONSE", "Failure"+t);
// moviesData.setValue(null);
}
});
return moviesData;
}
作为回应,当我看到时,我首先得到了数据,但所有其他回应,海报都是空的。
我调试检查的时候,(我没有发完整,我只拍了海报)
position 1:
Poster = "https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_SX300.jpg "
position 2:
Poster = null
position 3:
Poster = null
当我检查回复时,除了 position 1. 之外,除了 position 1. 之外,所有的海报都是 null。
电影回复:
public class MovieResponse implements Serializable {
@SerializedName("movies")
private List<Movies> movies;
public List<Movies> getMovies() {
return movies;
}
public void setMovies(List<Movies> movies) {
this.movies = movies;
}
}
MoviesViewModel:
public class MoviesViewModel extends AndroidViewModel {
private MutableLiveData<MovieResponse> mutableLiveData;
private MoviesRepository moviesRepository;
public MoviesViewModel(@NonNull Application application) {
super(application);
moviesRepository = new MoviesRepository(application);
}
public void init() {
if (mutableLiveData != null) {
return;
}
moviesRepository = MoviesRepository.getInstance();
mutableLiveData = moviesRepository.getMovieUpdates();
}
public MutableLiveData<MovieResponse> getNewsRepository() {
return moviesRepository.getMovieUpdates();
}
}
改造服务:
public class RetrofitService {
private static Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.myjson.com/bins/")
.addConverterFactory(GsonConverterFactory.create())
.build();
public static <S> S cteateService(Class<S> serviceClass) {
return retrofit.create(serviceClass);
}
}
public class MoviesRepository {
private static MoviesRepository moviesRepository;
private MovieApiInterface newsApi;
public static Application application;
public static MoviesRepository getInstance() {
if (moviesRepository == null) {
moviesRepository = new MoviesRepository(application);
}
return moviesRepository;
}
public MoviesRepository(Application application) {
this.application = application;
newsApi = RetrofitService.cteateService(MovieApiInterface.class);
}
public MutableLiveData<MovieResponse> getMovieUpdates() {
final MutableLiveData<MovieResponse> moviesData = new MutableLiveData<>();
newsApi.getMovieDetails().enqueue(new Callback<MovieResponse>() {
@Override
public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
if (response.isSuccessful()) {
if(response.body()!=null) {
moviesData.setValue(response.body());
}
}
}
@Override
public void onFailure(Call<MovieResponse> call, Throwable t) {
Log.i("RETROFIT RESPONSE", "Failure"+call.toString());
Log.i("RETROFIT RESPONSE", "Failure"+t);
// moviesData.setValue(null);
}
});
return moviesData;
}
}
主活动:
public class MainActivity extends AppCompatActivity {
MoviesAdapter newsAdapter;
RecyclerView rvHeadline;
MoviesViewModel newsViewModel;
List<Movies> newsArticles;
List<Movies> articleArrayList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rvHeadline = findViewById(R.id.rvNews);
articleArrayList = new ArrayList<>();
newsAdapter = new MoviesAdapter(MainActivity.this, articleArrayList);
rvHeadline.setLayoutManager(new LinearLayoutManager(this));
rvHeadline.setAdapter(newsAdapter);
newsViewModel = ViewModelProviders.of(this).get(MoviesViewModel.class);
newsViewModel.init();
newsViewModel.getNewsRepository().observe(this, newsResponse -> {
if (newsResponse != null) {
newsArticles = newsResponse.getMovies();
articleArrayList.addAll(newsArticles);
for(int i=0;i<articleArrayList.size();i++){
String poster = articleArrayList.get(i).getPoster();
Log.i("poster","poster"+poster);
}
newsAdapter.notifyDataSetChanged();
}
});
// setupRecyclerView();
}
private void setupRecyclerView() {
if (newsAdapter == null) {
newsAdapter = new MoviesAdapter(MainActivity.this, articleArrayList);
rvHeadline.setLayoutManager(new LinearLayoutManager(this));
rvHeadline.setAdapter(newsAdapter);
rvHeadline.setItemAnimator(new DefaultItemAnimator());
rvHeadline.setNestedScrollingEnabled(true);
} else {
newsAdapter.notifyDataSetChanged();
}
}
}
电影适配器:
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MoviesViewHolder> {
Context context;
List<Movies> articles;
public MoviesAdapter(Context context, List<Movies> articles) {
this.context = context;
this.articles = articles;
}
@NonNull
@Override
public MoviesAdapter.MoviesViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.movies_item, parent, false);
return new MoviesViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull MoviesAdapter.MoviesViewHolder holder, final int position) {
holder.tvName.setText(articles.get(position).getTitle());
holder.tvDesCription.setText(articles.get(position).getPoster());
String url = articles.get(position).getPoster();
if(url!=null) {
/* Glide.with(context) //passing context
.load(url) //passing your url to load image.
.dontAnimate()
.placeholder(context.getDrawable(R.drawable.ic_launcher_background)) //this would be your default image (like default profile or logo etc). it would be loaded at initial time and it will replace with your loaded image once glide successfully load image using url.
.centerCrop()//this method help to fit image into center of your ImageView
.into(holder.ivNews);*/ //pass imageView reference to appear the image.*/
Picasso.get()
.load(url)
.placeholder(R.drawable.ic_launcher_background)
.error(R.drawable.ic_launcher_background)
.into(holder.ivNews);
}
}
@Override
public int getItemCount() {
return articles.size();
}
public class MoviesViewHolder extends RecyclerView.ViewHolder {
TextView tvName;
TextView tvDesCription;
ImageView ivNews;
public MoviesViewHolder(@NonNull View itemView) {
super(itemView);
tvName = itemView.findViewById(R.id.tvName);
tvDesCription = itemView.findViewById(R.id.tvDesCription);
ivNews = itemView.findViewById(R.id.ivNews);
}
}
}
【问题讨论】:
-
我可以看看
MovieResponse类吗? json 响应中的 ** 也只是您的编辑吗? -
@IsraeldelaCruz 当然。我添加了电影响应类
-
除海报外,所有其他响应均正确。
-
你从哪里得到上面的 json 响应?来自
response还是来自浏览器?您是编辑它还是只是复制它? -
来自@IsraeldelaCruz 的响应我不想把所有的 json 响应都放在里面。所以我只是复制了一些并粘贴了它。这是那个网址。 api.myjson.com/bins/18buhu。您可以看到第一个 json 结构中缺少海报,而某些海报正在显示。所以改造总是为所有其他位置显示 null
标签: android android-studio retrofit android-livedata