英文:
ViewModel Observer shows empty RecyclerView
问题
以下是你提供的代码的翻译部分:
MainActivity:
public class MainActivity extends AppCompatActivity {
RecyclerView mMainRecycler;
MoviesViewModel moviesViewModel;
MainRecyclerAdapter mainRecyclerAdapter;
Context context = this;
List<String> genresNames = new ArrayList<>();
List<Integer> genresIds = new ArrayList<>();
List<List<Movies.Result>> listResults = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMainRecycler = findViewById(R.id.main_recycler);
moviesViewModel = new ViewModelProvider(this).get(MoviesViewModel.class);
moviesViewModel.getMoviesGenres();
moviesViewModel.mutableMoviesGenres.observe(this, new Observer<List<MoviesGenres.GenresBean>>() {
@Override
public void onChanged(List<MoviesGenres.GenresBean> genresBeans) {
for (int i = 0; i < genresBeans.size(); i++) {
genresIds.add(genresBeans.get(i).getId());
genresNames.add(genresBeans.get(i).getName());
}
}
});
for(int i = 0; i < genresIds.size(); i++) {
moviesViewModel.getMovieWithGenre(genresIds.get(i));
moviesViewModel.mutableMoviesWithGenre.observe(this, new Observer<List<Movies.Result>>() {
@Override
public void onChanged(List<Movies.Result> results) {
listResults.add(results);
}
});
}
mMainRecycler.setLayoutManager(new LinearLayoutManager(this));
mainRecyclerAdapter = new MainRecyclerAdapter(context, genresIds, listResults);
mMainRecycler.setAdapter(mainRecyclerAdapter);
}
}
Main Recycler Adapter:
public class MainRecyclerAdapter extends RecyclerView.Adapter<MainRecyclerAdapter.MainViewHolder> {
private Context context;
private List<List<Movies.Result>> moviesResults;
private List<Integer> moviesNames;
private Context mContext;
public MainRecyclerAdapter(Context context, List<Integer> moviesNames, List<List<Movies.Result>> moviesResults ) {
this.mContext = context;
this.moviesNames = moviesNames;
this.moviesResults = moviesResults;
}
@NonNull
@Override
public MainRecyclerAdapter.MainViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
return new MainViewHolder(LayoutInflater.from(mContext).inflate(R.layout.category_rv_item, parent, false));
}
@Override
public void onBindViewHolder(@NonNull final MainRecyclerAdapter.MainViewHolder holder, int position) {
holder.genresTv.setText(moviesNames.get(position).toString());
holder.mRecycler.setLayoutManager(new LinearLayoutManager(context, RecyclerView.HORIZONTAL, false));
MovieAdapter adapter = new MovieAdapter(moviesResults.get(position));
holder.mRecycler.setAdapter(adapter);
}
@Override
public int getItemCount() {
return moviesNames.size();
}
public class MainViewHolder extends RecyclerView.ViewHolder {
TextView genresTv;
RecyclerView mRecycler;
public MainViewHolder(@NonNull View itemView) {
super(itemView);
genresTv = itemView.findViewById(R.id.cat_title);
mRecycler = itemView.findViewById(R.id.item_recycler);
}
}
}
Child Recycler Adapter:
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MovieViewHolder> {
private List<Movies.Result> moviesResult;
public MovieAdapter(List<Movies.Result> moviesResult) {
this.moviesResult = moviesResult;
}
@NonNull
@Override
public MovieAdapter.MovieViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new MovieViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_item, parent, false));
}
@Override
public void onBindViewHolder(@NonNull MovieAdapter.MovieViewHolder holder, int position) {
String imageUrl = MoviesClient.IMAGE_URL + moviesResult.get(position).getPosterPath();
Glide.with(holder.mPosterImage.getContext()).load(imageUrl).into(holder.mPosterImage);
}
@Override
public int getItemCount() {
return moviesResult.size();
}
public class MovieViewHolder extends RecyclerView.ViewHolder {
ImageView mPosterImage;
public MovieViewHolder(@NonNull View itemView) {
super(itemView);
mPosterImage = itemView.findViewById(R.id.poster_image);
}
}
}
英文:
I'm trying to get some data from an API (using retrofit and MVVM), pass it to the adapter and the recyclerView, however when I run the app all I get is a blank white screen nothing shows up.
I made sure that there is no problem with the API or the data so the problem probably happened when I tried to implement and nested recyclerview.
MainActivity:
public class MainActivity extends AppCompatActivity {
RecyclerView mMainRecycler;
MoviesViewModel moviesViewModel;
MainRecyclerAdapter mainRecyclerAdapter;
Context context = this;
List<String> genresNames = new ArrayList<>();
List<Integer> genresIds = new ArrayList<>();
List<List<Movies.Result>> listResults = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMainRecycler = findViewById(R.id.main_recycler);
moviesViewModel = new ViewModelProvider(this).get(MoviesViewModel.class);
moviesViewModel.getMoviesGenres();
moviesViewModel.mutableMoviesGenres.observe(this, new Observer<List<MoviesGenres.GenresBean>>() {
@Override
public void onChanged(List<MoviesGenres.GenresBean> genresBeans) {
for (int i = 0; i < genresBeans.size(); i++) {
genresIds.add(genresBeans.get(i).getId());
genresNames.add(genresBeans.get(i).getName());
}
}
});
for(int i = 0; i < genresIds.size(); i++) {
moviesViewModel.getMovieWithGenre(genresIds.get(i));
moviesViewModel.mutableMoviesWithGenre.observe(this, new Observer<List<Movies.Result>>() {
@Override
public void onChanged(List<Movies.Result> results) {
listResults.add(results);
}
});
}
mMainRecycler.setLayoutManager(new LinearLayoutManager(this));
mainRecyclerAdapter = new MainRecyclerAdapter(context, genresIds, listResults);
mMainRecycler.setAdapter(mainRecyclerAdapter);
}
}
Main Recycler Adapter:
public class MainRecyclerAdapter extends RecyclerView.Adapter<MainRecyclerAdapter.MainViewHolder> {
private Context context;
private List<List<Movies.Result>> moviesResults;
private List<Integer> moviesNames;
private Context mContext;
public MainRecyclerAdapter(Context context, List<Integer> moviesNames, List<List<Movies.Result>> moviesResults ) {
this.mContext = context;
this.moviesNames = moviesNames;
this.moviesResults = moviesResults;
}
@NonNull
@Override
public MainRecyclerAdapter.MainViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
return new MainViewHolder(LayoutInflater.from(mContext).inflate(R.layout.category_rv_item, parent, false));
}
@Override
public void onBindViewHolder(@NonNull final MainRecyclerAdapter.MainViewHolder holder, int position) {
holder.genresTv.setText(moviesNames.get(position).toString());
holder.mRecycler.setLayoutManager(new LinearLayoutManager(context, RecyclerView.HORIZONTAL, false));
MovieAdapter adapter = new MovieAdapter(moviesResults.get(position));
holder.mRecycler.setAdapter(adapter);
}
@Override
public int getItemCount() {
return moviesNames.size();
}
public class MainViewHolder extends RecyclerView.ViewHolder {
TextView genresTv;
RecyclerView mRecycler;
public MainViewHolder(@NonNull View itemView) {
super(itemView);
genresTv = itemView.findViewById(R.id.cat_title);
mRecycler = itemView.findViewById(R.id.item_recycler);
}
}
}
Chile Recycler Adapter:
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.MovieViewHolder> {
private List<Movies.Result> moviesResult;
public MovieAdapter(List<Movies.Result> moviesResult) {
this.moviesResult = moviesResult;
}
@NonNull
@Override
public MovieAdapter.MovieViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new MovieViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.movie_item, parent, false));
}
@Override
public void onBindViewHolder(@NonNull MovieAdapter.MovieViewHolder holder, int position) {
String imageUrl = MoviesClient.IMAGE_URL + moviesResult.get(position).getPosterPath();
Glide.with(holder.mPosterImage.getContext()).load(imageUrl).into(holder.mPosterImage);
}
@Override
public int getItemCount() {
return moviesResult.size();
}
public class MovieViewHolder extends RecyclerView.ViewHolder {
ImageView mPosterImage;
public MovieViewHolder(@NonNull View itemView) {
super(itemView);
mPosterImage = itemView.findViewById(R.id.poster_image);
}
}
}
答案1
得分: 0
你忘记在获取列表后调用notifyDataSetChanged();
,因此适配器没有收到通知,无法显示recyclerView中的新数据。
另外,将第二个观察者移到for循环之外。你不需要每次都设置一个新的观察者。
修改为:
moviesViewModel.mutableMoviesWithGenre.observe(this, new Observer<List<Movies.Result>>() {
@Override
public void onChanged(List<Movies.Result> results) {
listResults.add(results);
}
});
for(int i = 0; i < genresIds.size(); i++) {
moviesViewModel.getMovieWithGenre(genresIds.get(i));
}
英文:
You forgot to call notifyDataSetChanged();
after fetching the list, due to this the adapter does not get notified that new data is available for display in recyclerView.
Also, move the second observer outside the for loop. You don't need to set a new observer every time.
Change to this:
moviesViewModel.mutableMoviesWithGenre.observe(this, new Observer<List<Movies.Result>>() {
@Override
public void onChanged(List<Movies.Result> results) {
listResults.add(results);
}
});
for(int i = 0; i < genresIds.size(); i++) {
moviesViewModel.getMovieWithGenre(genresIds.get(i));
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论