2015-05-09 32 views
0

我为具有两种类型的行的ListView创建了一个适配器。 ListView有4行。最后一行有不同的布局,这就是为什么我在getview中使用GetItemViewType方法的原因了解ViewHolder模式

我想了解该模式如何工作。我看着这样的: https://www.youtube.com/watch?v=bWsWe9T9HJw,以获得更好的理解 回收是如何工作的

什么,我不明白的是:当我在我的列表视图向下滚动,在convertview 总是空。当我再次滚动备份时,convertview不是null并且是可重用的。

不应该convertview为null只为列表中的第一个项目?我不明白为什么 它为每个新项目为空?只有在列表中的第一项

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

如果你的屏幕可以适合说2个视图,那么android会加载视图,2 visibile视图,并在底部的下一个视图,所以它至少需要4个views.This解释了为什么它不只是首先convertview null。顺便说一句,你应该检查与Api 21新的RecyclerView。 –

回答

1

不宜convertview为空?

通常不会。

我们假设这8行在ListView中可见。这意味着ListView将调用getView()至少8次,nullconvertView参数,以填充ListView中的可见空间。

ListView也可以缓存一些额外的行,以便能够快速响应滚动事件,作为缓存。

另外,在你的情况下,为每个视图类型维护单独的对象池。

如果您的适配器中有足够的东西,尽管如此,最终您还是会在最初的向下滚动过程中进行回收。这一切都取决于行的大小,适配器从getCount()返回的值等。

请注意,这与查看模式没有任何关系。

+0

我试图添加更多的项目列表,现在他们得到回收,所以这意味着你是正确的适配器回收后一定量的分配内存 – Joske369

0

通过此方法传递给您的View是显示在列表中的实际View(或如果需要创建一个,则为null)。

如果您的列表足够高以显示6个项目,例如它至少需要6个实例! 然而,当您滚动时,一个View会跳出窗口,并且可以重新用于列表的另一侧。

这对你有意义吗?

+0

10我不明白当一行离开列表顶部的窗口时,当我向下滚动时它不会被重用。列表项具有很大的高度,并且只有2个总是可见的 – Joske369