简体   繁体   中英

Problem while sorting a recycler view android studio

I have a recycler that shows different movies and you are able to rate them. Rating works ok but when hitting the sort button (that should arrange the movies from best to worst) everything just goes sort of nuts. This is the movie class that has the sorting method:

public static Comparator<Movie> MovieComparator = new Comparator<Movie>() {
    @Override
    public int compare(Movie m1, Movie m2) {
        return m1.getStars() - m2.getStars();
    }
};

And this is the mainActivity where I call the method when the sort button is clicked:

sortButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Collections.sort(movies, Movie.MovieComparator);
            adapter.notifyDataSetChanged();
        }
    });

And here is the whole Adapter class which handles the recycler (without import statements)

public class MoviesRecViewAdapter extends RecyclerView.Adapter<MoviesRecViewAdapter.ViewHolder> {

private ArrayList<Movie> movies = new ArrayList<>();
private Context context;

public MoviesRecViewAdapter(Context context) {
    this.context = context;
}

@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.movies_list_item, parent, false);
    ViewHolder holder = new ViewHolder(view);
    return holder;
}

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    holder.movie_title.setText(movies.get(position).getTitle());
    holder.movie_duration.setText(movies.get(position).getDuration() + " min");
    Uri uri = Uri.parse(movies.get(position).getImg());
    holder.movie_img.setImageURI(uri);
    holder.rating_bar.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
        @Override
        public void onRatingChanged(RatingBar ratingBar, float v, boolean b) {
            int rating = (int) v;
            movies.get(holder.getAdapterPosition()).setStars(rating);
            Toast.makeText(holder.itemView.getContext(), "Your rating was submitted", Toast.LENGTH_SHORT).show();
        }
    });

}

@Override
public int getItemCount() {
    return movies.size();
}

public void setMovies(ArrayList<Movie> movies) {
    this.movies = movies;
    notifyDataSetChanged();
}

public class ViewHolder extends RecyclerView.ViewHolder {

    private TextView movie_title;
    private TextView movie_duration;
    private ImageView movie_img;
    private RelativeLayout parent;
    private RatingBar rating_bar;
    public ViewHolder(@NonNull View itemView) {
        super(itemView);
        movie_title = itemView.findViewById(R.id.movie_title);
        movie_duration = itemView.findViewById(R.id.movie_duration);
        movie_img = itemView.findViewById(R.id.movie_img);
        parent = itemView.findViewById(R.id.parent);
        rating_bar = itemView.findViewById(R.id.rating_bar);
    }
}

}

Try calling adapter's setMovies method after sorting the list.

sortButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Collections.sort(movies, Movie.MovieComparator);
            adapter.setMovies(movies);
        }
    });

See there is this main recyclerview's recycling concept. And that is your items' viewholders are interchangable. For example viewholder1 is now pointing at video1, but when you call "notifyDataSetChanged", viewholder1 may point to video2.

So here's what you should do; you should keep each video's rating somewhere but not in viewholder (Because it recycles) and you should set the rating for each movie in "onBindViewHolder" method.

For more info I suggest reading the recyclerview.

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