0

I created an adapter for a ListView which has two types of rows. The ListView has 4 rows. The last row has a different layout, that's why i use the GetItemViewType method in getview

I'm trying to understand how the pattern works. I watched this: https://www.youtube.com/watch?v=bWsWe9T9HJw to get a better understanding of how recycling works

What i don't understand is: when i scroll down in my listview, the convertview is always null. When i scroll back up again, the convertview is not null and is reusable.

Shouldn't convertview be null only for the first item in the list? i don't get why it is null for each new item?

public override View GetView (int position, View convertView, ViewGroup parent)
    {
        BaseBundelVO bundle = _bundles [position];

        DSBundleListItem bundleHolder = null;
        DSBundleArchiveItem archiveHolder = null;

        int type = GetItemViewType(position);
        if (convertView == null)
        {
            bundleHolder = new DSBundleListItem (_activity);
            archiveHolder = new DSBundleArchiveItem (_activity);

            switch (type) 
            {
            case 0:
                convertView = _activity.LayoutInflater.Inflate (Resource.Layout.dsBundleListItem, null);
                bundleHolder.IconIv = convertView.FindViewById<ImageView> (Resource.Id.iconIv);
                bundleHolder.CoverIv = convertView.FindViewById<ImageView> (Resource.Id.coverIv);
                bundleHolder.CoverTitleTv = convertView.FindViewById<TextView> (Resource.Id.coverTitleTv);
                bundleHolder.CoverSubTitleTv = convertView.FindViewById<TextView> (Resource.Id.coverSubTitleTv);
                bundleHolder.BundleProgress = convertView.FindViewById<ProgressBar> (Resource.Id.bundleProgress);
                convertView.Tag = bundleHolder;
                break;
            case 1:
                convertView = _activity.LayoutInflater.Inflate (Resource.Layout.dsBundleArchiveItem, null);
                archiveHolder.ArchiveTitleTv = convertView.FindViewById<TextView> (Resource.Id.archiveTitleTv);
                archiveHolder.ArchiveSubTitleTv = convertView.FindViewById<TextView> (Resource.Id.archiveSubTitleTv);
                convertView.Tag = archiveHolder;
                break;
            }

        } 
        else 
        {
            switch (type) 
            {
            case 0:
                bundleHolder = (DSBundleListItem)convertView.Tag;
                Console.WriteLine (bundleHolder.IsDisposed ());
                bundleHolder.RemoveImageLoaderCallBack ();
            break;
            case 1:
                archiveHolder = (DSBundleArchiveItem)convertView.Tag;
                Console.WriteLine (archiveHolder.IsDisposed ());
                archiveHolder.RemoveImageLoaderCallBack ();
            break;
            }
        }

        switch (type) 
        {
        case 0:
            bundleHolder.CoverTitleTv.Text = bundle.Title;
            bundleHolder.CoverSubTitleTv.Text = bundle.SubTitle;
            bundleHolder.LoadImage(bundle.CoverImageLocation,bundle.Icon);
            break;
        case 1:
            archiveHolder.ArchiveTitleTv.Text    = "Archief";
            archiveHolder.ArchiveSubTitleTv.Text = "Bekijk onze eerder verschenen publicaties";
            break;
        }

        return convertView;
    }
Joske369
  • 505
  • 1
  • 6
  • 18
  • If your screen can fit say 2 views, then android will load the view up, the 2 visibile views, and the next view at the bottom, So it needs at least 4 views.This explains why it isn't just the first convertview null. Btw FIY you should check the new RecyclerView with Api 21. – Federico Ponzi May 09 '15 at 15:11

2 Answers2

1

Shouldn't convertview be null only for the first item in the list?

Not usually.

Let's suppose that that 8 rows are visible in the ListView. That means the ListView will call getView() at least 8 times with null for the convertView parameter, to populate the visible space in the ListView.

ListView may also cache a few additional rows, to be able to rapidly respond to scrolling events, as a cache.

Plus, in your case, there are separate object pools maintained for each view type.

If your adapter has enough stuff in it, though, eventually you will recycle even during the initial scroll down. It all depends on the size of the rows, the values that the adapter returns from getCount(), etc.

And note that this has nothing really to do with the view holder pattern.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • I tried adding more items to the list and now they get recycled, so this means you were right about the adapter recycling after a certain amount of allocated memory – Joske369 May 09 '15 at 15:10
0

The View that is passed to you in this method is the actual View that is displayed in the list (or null if it needs you to create one).

If your list is tall enough to show 6 items, for instance, it does need to have at least 6 instances at its disposal! When you scroll however, one View gets out of the window, and can be reused for the other side of the list.

Does that make sense to you?

BoD
  • 10,838
  • 6
  • 63
  • 59
  • i don't understand that when a row goes out of the window on the top of the list, it doesn't get reused when i'm scrolling down. the list items have a large height and only 2 are always visible on the screen – Joske369 May 09 '15 at 15:07