2015-05-09 54 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