title: Why does my StaggeredGrid RecyclerView layout every item, not only visible ones?
body: <p>I have a Staggered grid containing 370 items, with images. </p>
  
  <p>I want to make sure the items are recycled quickly to be careful with memory, but a ViewHolder is created and then bound for every single item in my adapter and pays no attention to whether children are visible</p>
  
  <p><strong>I've tried the following</strong></p>
  
  <pre><code>StaggeredGridLayoutManager lm = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
  rv.setLayoutManager(lm);
  
  rv.setItemViewCacheSize(20); //Has no effect
  
  RecyclerView.RecycledViewPool pool = new RecyclerView.RecycledViewPool();
  pool.setMaxRecycledViews(0, 20);
  rv.setRecycledViewPool(pool); //also has no effect
  </code></pre>
  
  <p>Logging shows onCreateViewHolder and onBindViewHolder are called 185 times each. Then onViewRecycled is called 185 times before resuming calls to onCreateViewHolder until we reach the full 370.</p>
  
  <p>This could be an understanding problem on my part, but I think the RecyclerView should bind only those view that are visible, or to honor having only 20 views, or 20 in pool + however many fit on screen. How can I make this happen with the StaggeredGridLayoutManager?</p>
  
  <p>If I listen to scroll changes and use findFirstCompletelyVisibleItemPositions, and findLastCompletelyVisibleItemPositions this still spans every single item in the adapter, not just the 6 that fit on screen</p>
  
  <p><strong>My adapter code</strong></p>
  
  <pre><code>class MyAdapter extends RecyclerView.Adapter&lt;MyViewHolder&gt; {
  
      static final int NUM_COLS = 3;
      private final LayoutInflater mInflater;
      private final List&lt;GridItem&gt; mEntries;
      private int mLastExpanded; //stores where the last expanded item was
      private OnCardClickListener mOnItemClick;
  
      MyAdapter(Context context) {
          super();
          mEntries = new ArrayList&lt;&gt;();
          mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      }
  
      void setOnTileClickListener(@Nullable OnCardClickListener listener) {
          mOnItemClick = listener;
          notifyDataSetChanged(); //recall bind logic
      }
  
      void setItems(Collection&lt;GridItem&gt; items) {
          mEntries.clear();
          mEntries.addAll(items);
          sort();
      }
  
      @WorkerThread
      private void sort() {
          Collections.sort(mEntries, (thisEntry, otherEntry) -&gt; {
              int ret;
              if (otherEntry == null || thisEntry.getCreated() == otherEntry.getCreated()) {
                  ret = 0;
              } else if (thisEntry.getCreated() &gt; otherEntry.getCreated()) {
                  ret = -1;
              } else {
                  ret = 1;
              }
              return ret;
          });
      }
  
      @Override
      public int getItemCount() {
          return mEntries.size();
      }
  
      private GridItem getItem(int position) {
          return mEntries.get(position);
      }
  
      @Override
      public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
          return new MyViewHolder(mInflater.inflate(R.layout.li_grid_item, parent, false));
      }
  
      @Override
      public void onViewRecycled(MyViewHolder holder) {
          super.onViewRecycled(holder);
          holder.onViewRecycled(); //clears bitmap reference
      }
  
      @Override
      public void onBindViewHolder(MyViewHolder holder, int position) {
          determineTileSize(holder, position);
          holder.bind(getItem(position),  mOnItemClick);
      }
  
      private void determineTileSize(MyViewHolder holder, int position) {
          ViewGroup.LayoutParams cardParams = holder.getCardLayout().getLayoutParams();
          StaggeredGridLayoutManager.LayoutParams gridItemParams = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams();
          if (shouldBeExpanded(position)) {
              cardParams.height = (int) holder.getCard().getResources().getDimension(R.dimen.spacing_card_large);
              mLastExpanded = position;
              gridItemParams.setFullSpan(true);
          }
          holder.getCardLayout().setLayoutParams(cardParams);
      }
  
      private boolean shouldBeExpanded(int position) {
          return position &gt; (mLastExpanded + NUM_COLS);  //minimum 1 row between enlarged
      }
  
  }
  </code></pre>
  
  <p><strong>My Activity Layout Structure</strong></p>
  
  <pre><code>&lt;android.support.design.widget.CoordinatorLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto" ...&gt;
      &lt;android.support.design.widget.AppBarLayout ...&gt;
          &lt;android.support.design.widget.CollapsingToolbarLayout ...&gt;
              &lt;android.support.v7.widget.Toolbar
                  android:layout_width="match_parent"
                  android:layout_height="?attr/actionBarSize"
                  app:layout_collapseMode="pin" ... /&gt;
              &lt;android.support.design.widget.TabLayout ...
                  app:layout_collapseMode="pin"
                  android:layout_width="wrap_content"
                  android:layout_height="?attr/actionBarSize" /&gt;
          &lt;/android.support.design.widget.CollapsingToolbarLayout&gt;
      &lt;/android.support.design.widget.AppBarLayout&gt;
      &lt;FrameLayout
          android:id="@+id/fragment_container"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          app:layout_behavior="@string/appbar_scrolling_view_behavior" /&gt;
      &lt;FrameLayout
          android:id="@+id/bottom_sheet"
          android:layout_width="match_parent"
          android:layout_height="@dimen/height_backdrop"
          android:minHeight="@dimen/height_backdrop"
          android:background="@color/colorAccent"
          android:visibility="gone"
          app:elevation="@dimen/spacing_narrow"
          app:behavior_peekHeight="0dp"
          app:behavior_hideable="true"
          app:layout_behavior="android.support.design.widget.BottomSheetBehavior" /&gt;
  &lt;/android.support.design.widget.CoordinatorLayout&gt;
  </code></pre>
  
  <p><strong>Fragment Layout</strong></p>
  
  <pre><code>&lt;android.support.v4.widget.NestedScrollView
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      app:layout_behavior="@string/appbar_scrolling_view_behavior" ...&gt;
  
      &lt;RelativeLayout
          android:layout_width="match_parent"
          android:layout_height="match_parent"&gt;
  
          &lt;android.support.v7.widget.RecyclerView
              android:id="@+id/grid_recycler_view"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" /&gt;
  
              &lt;!-- Empty and loading views --&gt;
  
      &lt;/RelativeLayout&gt;
  
  &lt;/android.support.v4.widget.NestedScrollView&gt;
  </code></pre>