简体   繁体   中英

ViewModel Observer shows empty RecyclerView

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);
        }
    }
}

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));
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM