RecyclerView refreshes items only when scrolling down and up

蹲街弑〆低调 提交于 2019-12-22 04:33:20

问题


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.


回答1:


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.




回答2:


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...




回答3:


Adding this solved the problem to me

layoutManager.scrollToPosition


来源:https://stackoverflow.com/questions/29460164/recyclerview-refreshes-items-only-when-scrolling-down-and-up

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!