Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RecyclerView refreshes items only when scrolling down and up

I am making a simple recyclerview with Movie items. When I try adding new items they won't display in the recyclerview right away. For some reason I have to scroll down so the first item is gone, and then up again for the new item to be displayed (it's added at index 0).

The adapter:

public class MovieCardAdapter extends RecyclerView.Adapter<MovieCardAdapter.MovieViewHolder> {
List<Movie> movieList;

public MovieCardAdapter(final List<Movie> movieList) {
    this.movieList = movieList;
}

public void addItem(int position, final Movie movie){
    movieList.add(position,movie);
    notifyItemInserted(position);
}

public void removeItem(final Movie movie){
    final int indexOf = movieList.indexOf(movie);
    movieList.remove(movie);
    notifyItemRemoved(indexOf);
}

public void updateItems(final List<Movie> items){
    movieList = items;
    notifyDataSetChanged();
}

@Override
public MovieViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View itemView = LayoutInflater.
            from(viewGroup.getContext()).
            inflate(R.layout.movie_row, viewGroup, false);

    return new MovieViewHolder(itemView);
}

@Override
public long getItemId(int position) {
    return super.getItemId(position);
}

@Override
public void onBindViewHolder(final MovieViewHolder movieViewHolder, final int i) {
    final Movie movie = movieList.get(i);

    String posterUrl = "";
    final int posterHeight = 240;
    if (!isEmpty(movie.getImdb_id())) {
        posterUrl = "http://img.omdbapi.com/?i=" + movie.getImdb_id() + "&apikey="+apiKey+"&h=" + posterHeight;
    } else if (!isEmpty(movie.getPoster())) {
        posterUrl = movie.getPoster();
    }
    if (!isEmpty(posterUrl)) {
        Picasso.with(movieViewHolder.context)
                .load(posterUrl)
                .resize(220, 354)
                .centerCrop()
                .into(movieViewHolder.poster);
    }

    movieViewHolder.title.setText(movie.getTittel());
    movieViewHolder.format.setText(movie.getFormat());

    if (movie.getRuntime().isEmpty() || movie.getRuntime().equalsIgnoreCase("0")){
        movieViewHolder.runtime.setText("");
    }else{
        movieViewHolder.runtime.setText(movie.getRuntime()+" mins");
    }

    if (!movie.getTagline().isEmpty()) {
        movieViewHolder.tagline.setText(movie.getTagline());
    } else if (!movie.getPlot().isEmpty()) {
        movieViewHolder.tagline.setText(movie.getPlot());
    }
}

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

public static class MovieViewHolder extends RecyclerView.ViewHolder {
    protected Context context;
    protected LinearLayout movieRowLinearLayout;
    protected ImageView poster;
    protected TextView title;
    protected TextView runtime;
    protected TextView tagline;
    protected TextView format;

    public MovieViewHolder(View v) {
        super(v);
        context = v.getContext();
        movieRowLinearLayout = (LinearLayout) v.findViewById(R.id.movieRowLinearLayout);
        poster = (ImageView) v.findViewById(R.id.poster);
        title = (TextView) v.findViewById(R.id.title);
        runtime = (TextView) v.findViewById(R.id.runtime);
        tagline = (TextView) v.findViewById(R.id.tagline);
        format = (TextView) v.findViewById(R.id.format);
    }
}

}

Initializing the adapter:

adapter = new MovieCardAdapter(MovieList.movies);
recyclerView.setAdapter(adapter);

Adding a sample movie:

if (id == R.id.add_movie) {
        final Movie movie = new Movie();
        movie.setTittel("0TEST");
        movie.setFormat("HD-DVD");

        MovieList.sortMoviesByTitle();
        adapter.addItem(MovieList.movies.indexOf(movie), movie);
        return true;
    } else if (id == R.id.action_logOut) {
        logOut(this);
    }

Sry bad english, hope someone understands and know what the problem might be. I have tried adding from runOnUiThread([...]), but same result.

like image 769
Olav Gulbrandsen Blaaflat Avatar asked Apr 05 '15 17:04

Olav Gulbrandsen Blaaflat


2 Answers

This is happening because position 0 is above the current visible screen. Until transcript mode is implemented, when you are adding an item to position N, try calling scrollToPosition(N) if LinearLayoutManager#findFirstCompletelyVisibleItemPosition returns N.

Also, don't make the position parameter final in your onBindViewHolder method. Instead, use ViewHolder.getPosition() if you need it in a callback. When position of the item changes, you will not receive an onBind call unless the item itself is invalidated.

Update

Also your update logic is not correct because you are not clearing values in views.

if (!movie.getTagline().isEmpty()) {
    movieViewHolder.tagline.setText(movie.getTagline());
} else if (!movie.getPlot().isEmpty()) {
    movieViewHolder.tagline.setText(movie.getPlot());
} else {
    movieViewHolder.tagline.setText(null);
}

Same for the poster URL.

like image 170
yigit Avatar answered Sep 19 '22 09:09

yigit


layoutManager.scrollToPosition didn't solve the problem for me.

Not a definitive solution, but the following line did the trick in my case:

recyclerView.getLayoutManager().smoothScrollToPosition(recyclerView, null, 0);

Hope it helps...

like image 43
gbruscatto Avatar answered Sep 22 '22 09:09

gbruscatto