我从互联网上获取电影数据,如名字,海报等,但是对于电影的类型,我需要从网上再次获取它。所以这是我解决这个问题的方法。
public class MoviesViewAllAdapter extends RecyclerView.Adapter<MoviesViewAllAdapter.MoviesViewHolder> {
private Context mContext;
private List<MovieBrief> mMovies;
public MoviesViewAllAdapter(Context context, List<MovieBrief> movies) {
mContext = context;
mMovies = movies;
}
@Override
public MoviesViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new MoviesViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_movie_large,parent,false));
}
@Override
public void onBindViewHolder(MoviesViewHolder holder, int position) {
holder.movieGenreTextView.setText("");
setGenres(holder, mMovies.get(position).getId());
}
@Override
public int getItemCount() {
return mMovies.size();
}
public class MoviesViewHolder extends RecyclerView.ViewHolder {
public TextView movieGenreTextView;
public MoviesViewHolder(View itemView) {
super(itemView);
movieGenreTextView = (TextView) itemView.findViewById(R.id.text_view_genre_movie_card);
}
}
private void setGenres(final MoviesViewHolder holder, Integer movieId) {
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<Movie> call = apiService.getMovieDetails(movieId,mContext.getResources().getString(R.string.MOVIE_DB_API_KEY));
call.enqueue(new Callback<Movie>() {
@Override
public void onResponse(Call<Movie> call, Response<Movie> response) {
if(response.code() != 200) return;
List<Genre> genresList = response.body().getGenres();
String genres = "";
for (int i=0;i<genresList.size();i++) {
if(i == genresList.size()-1) {
genres = genres.concat(genresList.get(i).getGenreName());
}
else {
genres = genres.concat(genresList.get(i).getGenreName()+", ");
}
}
holder.movieGenreTextView.setText(genres);
}
@Override
public void onFailure(Call<Movie> call, Throwable t) {
}
});
}
}
但是这里的问题是,当执行fling并向上回收者视图显示的类型与电影无关时,正在加载的类型是随机的。 可能是因为我在onBindViewHolder上加载数据,当持有者从屏幕上消失时,它会加载到随机持有者中。是这样吗?
答案 0 :(得分:1)
我相信您的问题是,每次在列表中创建视图时,您都会获得整个电影列表。我不确定服务器是如何返回该数据的,但我的猜测是每次调用服务器时都无法保证数据的顺序相同。你每次都会得到一个随机的顺序,但是试图提取它的固定位置,这就是为什么类型不相关的原因。
有问题的行是onBindViewHolder
,每次创建一个视图时都会调用该行,并且此函数正在调用setGenres
,它正在获取一个随机顺序的新电影列表。
你可以做两件事来解决这个问题:
首先获取列表,将其作为ArrayList存储在适配器中。现在迭代它,而不必每次都调用服务器
public class MoviesViewAllAdapter extends RecyclerView.Adapter<MoviesViewAllAdapter.MoviesViewHolder> {
.
.
.
List<Movie> list = new ArrayList<>;
public void setList(List movies){
//get data from server before creating the adapter. call this on your adapter and store the data here
this.list = movies;
}
private void setGenres(final MoviesViewHolder holder, Integer movieId){
//iterate the field list instead of calling the server
}
.
.
.
}
答案 1 :(得分:1)
显示错误类型的问题是由RecyclerView执行的视图/持有者的回收引起的。当您滚动MoviesViewHolder的实例并重复使用视图时,当您触发加载电影详细信息时ViewHolder与MovieRef相关联,但是当获取电影详细信息的调用结束时,持有者现在被分配给不同的电影。
我认为最好的办法是加载电影详细信息并将其缓存在地图中,例如{API},当调用API结束时,您可以将Movie对象存储在那里。
HashMap<Integer, Movie> mMoviesDetails;
然后在您的适配器中,您可以将onBindViewHolder更改为如下所示:
public void onResponse(Call<Movie> call, Response<Movie> response) {
if(response.code() != 200) return;
mMoviesDetails.put(movieId, response.body());
notifyDataSetChanged();
}
这只是基于您当前实现的示例代码,一般来说我不会在Adapter中加载这些数据,而是将这种类型的任务委托给一个专用的API类,它可以将数据存储在像Realm这样的数据库中,而不是使用地图。