title: Lazy loading ViewPagers in a ScrollView
body: <p>Im trying to inflate multiple <code>ViewPagers</code> into a <code>ScrollView</code> where each <code>ViewPager</code> is using a FragmentStatePagerAdapter. </p>
  
  <p>The <code>ViewPager</code> consist of fragments with three <code>ImageViews</code> for each page.</p>
  
  <p>Im using UniversalImageLoader for the async loading of the images but I cant get a lazy load to work. </p>
  
  <p>The problem is when my app is inflating lets say 10 <code>ViewPagers</code> with 3 <code>ImageViews</code> for each <code>TripplePosterFragment1</code>, and another 10 <code>ViewPagers</code> with 3 <code>ImageViews</code> for <code>TripplePosterFragment2</code> since the <code>mPager.setOffscreenPageLimit(1)</code> kicks in. </p>
  
  <p>Its a total of 60 async requests firing during my <code>progressLayout</code> is visible.</p>
  
  <p>My <code>MainFragment</code> with following method:</p>
  
  <pre><code>private void renderSubCarousels(ArrayList&lt;Carousel&gt; carousels) {
  
      LayoutInflater mInflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  
      int i = 1;
  
      LinearLayout subCarouselLayout = (LinearLayout) mScrollView.findViewById(R.id.index_subcategory_carousel_container);
  
      for (final Carousel carousel : carousels) {
  
          RelativeLayout carouselWrapper = (RelativeLayout) mInflater.inflate(R.layout.main_pager_layout, null);
          LinearLayout mContainer = (LinearLayout) carouselWrapper.findViewById(R.id.main_pager_container);
          mContainer.setId(Constants.BASEID_LINEARLAYOUT + i);
  
          ViewPager mPager = (ViewPager) mContainer.findViewById(R.id.main_pager);   
          mPager.setId(Constants.BASEID_VIEWPAGER + i);
          mPager.setAdapter(new PagerPosterAdapter(getFragmentManager(),Constants.TRIPLE_POSTERS, carousel));
          subCarouselLayout.addView(carouselWrapper);
          i++;
      }
      progressLayout.setVisibility(View.GONE);
  }
  </code></pre>
  
  <p>My <code>FragmentStatePagerAdapter</code>:</p>
  
  <pre><code>public class PagerPosterAdapter extends FragmentStatePagerAdapter {
      private int mPageSize;
      private Carousel mCarousel;
  
      public PagerPosterAdapter(FragmentManager fm, int pageSize, Carousel carousel) {
          super(fm);
          this.mPageSize = pageSize;
          this.mCarousel = carousel;
      }
  
      @Override
      public int getCount() {
          int maxPageIndex = (int) Math.ceil((float) mCarousel.getAssets().size() / mPageSize);     
          return maxPageIndex;
      }
  
      @Override
      public Fragment getItem(int position) {
          ArrayList&lt;Asset&gt; assets = mCarousel.getAssets();
          int from = position*mPageSize;
          int to = (position+1)*(mPageSize);
          if(to &gt; assets.size()-1)
              to = assets.size();
  
          return (TripplePosterFragment.newInstance(assets.subList(from,  to)));
      }
  }
  </code></pre>
  
  <p>The <code>TripplePosterFragment</code> where the ImageView rendering happens:</p>
  
  <pre><code>private void initViews() {
  
      ImageView mFirstImageView = (ImageView) mLinearLayout.findViewById(R.id.first_pager_poster);        
      ImageView mSecondImageView = (ImageView)mLinearLayout.findViewById(R.id.second_pager_poster);
      ImageView mThirdImageView = (ImageView)mLinearLayout.findViewById(R.id.third_pager_poster);
  
      for(int i = 0;i &lt; assets.size(); i++){
  
          ImageView image = null;
  
          switch(i){
          case 0:
              image = (ImageView) mLinearLayout.findViewById(R.id.first_pager_poster);
              break;      
          case 1:
              image = (ImageView) mLinearLayout.findViewById(R.id.second_pager_poster);
                  break;
          case 2:
              image = (ImageView) mLinearLayout.findViewById(R.id.third_pager_poster);
              break;
          default:
              continue;   
          }
  
          //The ScrollView in MainFragment
  
          CustomScrollView mParentScrollView = (CustomScrollView)getActivity().findViewById(R.id.index_scrollviewparent);
  
          Rect scrollBounds = new Rect();
          mParentScrollView.getHitRect(scrollBounds);
          if (image.getLocalVisibleRect(scrollBounds)) {
              // Any portion of the imageView, even a single pixel, is within the visible window
              ImageLoader.getInstance().displayImage(assets.get(i).getPoster(), image);
              System.out.println("Im within");
          else {
              // NONE of the imageView is within the visible window
              System.out.println("Im NOT within");
          }
      }
  }
  </code></pre>
  
  <p>I need to check if the images are visible and load them when they are. But <code>System.out.println("Im NOT within");</code> is spammed in the <code>Log</code>. Im sure there is a way of doing it similar to this, but I need some help.</p>
  
  <p>I've tried a quick approach of doing much of the meat inside a ListView but its not optimal, at least after some reading, <a href="https://stackoverflow.com/questions/8674529/viewpager-inside-listview">ViewPager inside ListView</a></p>
  
  <p><strong>UPDATE</strong></p>
  
  <p>Same core issue as before, but using a new approach HorizontalListViews instad of Pagers.</p>
  
  <p><code>ListViews</code> seems like the way to go. By using <code>ArrayAdapter</code> to populate a regular vertical <code>ListView</code> with multiple <code>HListViews</code> lazy loads the images vertically for each new row, and horizontally for each image inside, as intended. </p>
  
  <p><strong>Problem:</strong>  Horizontal positions are lost. The <code>horizontalAdapter</code> is inherited from a recycled view onto next list item. This <em>positions</em> the new list item to where the recycled list item was.</p>
  
  <pre><code>public View getView(int position, View convertView, ViewGroup parent) {
      final ViewHolder holder;
      View view = convertView;
  
      if (view == null) {
          holder = new ViewHolder();
          view = mInflater.inflate(R.layout.carousel_frame_layout, null);
          holder.carouselList = (HListView) view.findViewById(R.id.hListView);
          view.setTag(holder);
      }
      else {
          holder = (ViewHolder) view.getTag();
      }
      Carousel mCarousel = mData.get(position);
  
      // Problem: Re-uses adapters from convertview
      if (holder.carouselList.getAdapter() == null) {
          SubCategoryCarouselAdapter horizontalAdapter = new SubCategoryCarouselAdapter(mContext, mCarousel.getAssets());
          holder.carouselList.setAdapter(horizontalAdapter);
      } else {
          ((SubCategoryCarouselAdapter) holder.carouselList.getAdapter()).update(mCarousel.getAssets());
      }
  
      return view;
  }
  </code></pre>
  
  <p>The solution could be to save the inner <code>horizontalAdapter</code> to a designated list item position, but I dont know how to do this when the <code>HListView</code> itself is recycled. </p>
  
  <p><strong>UPDATE 3</strong></p>
  
  <p>Found a working solution for <code>HListViews</code>. But I have still to test if this is working for <code>ViewPagers</code>.  </p>
  
  <p>Its lazy loading images both horizontally and vertically when using <code>addHeaderView</code> on parent <code>ListView</code> for each inner <code>HListView</code>. I´ve used <a href="https://github.com/sephiroth74/HorizontalVariableListView" rel="nofollow noreferrer">HorizontalVariableListView</a> together with <a href="https://github.com/nostra13/Android-Universal-Image-Loader" rel="nofollow noreferrer">UniversalImageLoader</a> for the carousels. </p>
  
  <pre><code>LayoutInflater mInflater = (LayoutInflater) getActivity().getSystemService
              (Context.LAYOUT_INFLATER_SERVICE);
  
  for (final Carousel carousel : carousels) {
      View carouselWrapper = mInflater.inflate(R.layout.carousel_sub_category_layout, null);
      listView.addHeaderView(carouselWrapper);
      listView.setAdapter(null);
  
      HListView horizontalList = (HListView) carouselWrapper.findViewById(R.id.hListView);
      SubCategoryCarouselAdapter mAdapter = new SubCategoryCarouselAdapter(getActivity(), carousel.getAssets());
      horizontalList.setAdapter(mAdapter);
  }
  </code></pre>