Understanding the ViewHolder pattern

╄→尐↘猪︶ㄣ 提交于 2019-12-25 10:01:15

问题


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;
    }

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




回答2:


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?



来源:https://stackoverflow.com/questions/30141323/understanding-the-viewholder-pattern

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