title: RecyclerView creating and binding all ViewHolders when scrolling
body: <p>I have a weird issue which I cannot pinpoint. My app fetches movie data from a website, and specifically, a poster image. I created a RecyclerView that is supposed to show all of the posters in a 2-column grid.</p>
  
  <p>Scrolling experience is extremely laggy, and for some reason the items are swapping places mid-scroll even though there are no changes in the data list.</p>
  
  <p>I tried debugging the app, and found out that on the first time I call notifyDataSetChanged() my adapter would call onCreateViewHolder(...) for <strong>every</strong> item in my list (around 90 times, when only 6 posters are visible at any given moment), and same goes for onBindViewAdapter(...).
  Then, when scrolling, it would recreate and rebind all ViewHolders again!</p>
  
  <p>I have checked my code again and again and haven't been able to determine the cause. Your help will be greatly appreciated.</p>
  
  <p>RecyclerView.adapter:</p>
  
  <pre><code>public class MovieRecyclerViewAdapter extends RecyclerView.Adapter&lt;MovieRecyclerViewAdapter.ViewHolder&gt; {
      private final Cinema cinema;
      private final List&lt;Movie&gt; movies;
      private final Context context;
      private final DisplayMetrics displayMetrics;
      private final Picasso picasso;
  
      public MovieRecyclerViewAdapter(Context context, Cinema cinema, List&lt;Movie&gt; movies) {
          this.context = context;
          this.cinema = cinema;
          this.movies = movies;
  
          WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
          displayMetrics = new DisplayMetrics();
          wm.getDefaultDisplay().getMetrics(displayMetrics);
  
          // Set up Picasso with okHttp3
          okhttp3.OkHttpClient okHttp3Client = new okhttp3.OkHttpClient();
          OkHttp3Downloader okHttp3Downloader = new OkHttp3Downloader(okHttp3Client);
          picasso = new Picasso.Builder(context)
                  .downloader(okHttp3Downloader)
                  .build();
      }
  
      @Override
      public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
          View view = LayoutInflater.from(parent.getContext())
                  .inflate(R.layout.fragment_movies, parent, false);
          return new ViewHolder(view);
      }
  
      @Override
      public void onBindViewHolder(final ViewHolder holder, int position) {
          Movie movie = movies.get(position);
          int imgViewWidth = displayMetrics.widthPixels / 2;
          int imgViewHeight = (int)(imgViewWidth * 1.4);
          picasso.with(context)
                  .load(cinema.getPosterUrl(movie))
                  .resize(imgViewWidth, imgViewHeight)
                  .into(holder.imageView);
      }
  
      @Override
      public int getItemCount() {
          return movies.size();
      }
  
      public class ViewHolder extends RecyclerView.ViewHolder {
          public ImageView imageView;
  
          public ViewHolder(View view) {
              super(view);
              this.imageView = (ImageView) view.findViewById(R.id.fragment_movies_poster);
          }
      }
  }
  </code></pre>
  
  <p>RecyclerView item layout:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;ImageView xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/fragment_movies_poster"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"&gt;
  
  &lt;/ImageView&gt;
  </code></pre>
  
  <p>RecyclerView XML definition:</p>
  
  <pre><code>&lt;android.support.v7.widget.RecyclerView
          android:id="@+id/fragment_movies_recycler_view"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          tools:listitem="@layout/fragment_movies" /&gt;
  </code></pre>
  
  <p>RecyclerView configuration, setting adapter:</p>
  
  <pre><code>@Override
      public View onCreateView(LayoutInflater inflater, ViewGroup container,
                               Bundle savedInstanceState) {
          View view = inflater.inflate(R.layout.fragment_movies_grid, container, false);
  
          Context context = view.getContext();
          RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.fragment_movies_recycler_view);
          recyclerView.setLayoutManager(new GridLayoutManager(context, columnCount));
          movies = new ArrayList&lt;&gt;();
          adapter = new MovieRecyclerViewAdapter(context, cinema, movies);
          recyclerView.setAdapter(adapter);
          recyclerView.setHasFixedSize(true);
  
          fetchMovies(view); // Populates movies list
  
          return view;
      }
  </code></pre>
  
  <hr>
  
  <p><strong>EDIT</strong></p>
  
  <p>Since posting this question I found a similar question: <a href="https://stackoverflow.com/questions/37254251/android-recyclerview-creates-and-binds-all-the-views-on-dataset-change">Android RecyclerView Creates and Binds all the views on Dataset change</a></p>
  
  <p>Indeed, once I set the item layout_height to a fixed value rather than "wrap_content" the issue is fixed. Apparently the RecyclerView tries to create all its views in order to determine its height.</p>
  
  <p>However, I tried the solution offered in that question, calling the LayoutManager's <code>lm.setAutoMeasureEnabled(false)</code> with layout_height set to "wrap_content" and the issue persisted. Are there any suggestions how would I have an adaptive layout_height without this issue occurring?</p>