2014-09-22 98 views
10

我有一個簡單的代碼片段來實現自定義列表視圖。在ViewHolder模式中,setTag和getTag的作用是什麼?

我的代碼如下:

WeatherAdapter.java:

public class WeatherAdapter extends ArrayAdapter<weather>{ 

    Context mcontext; 
    int mlayoutResourceId;  
    weather mdata[] = null; 
    View row; 

    public WeatherAdapter(Context context, int layoutResourceId, weather[] data) { 
     super(context, layoutResourceId, data); 
     mlayoutResourceId = layoutResourceId; 
     mcontext = context; 
     mdata = data; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     row = convertView; 
     WeatherHolder holder = null; 

     if(row == null) 
     { 
      LayoutInflater inflater = ((Activity) mcontext).getLayoutInflater(); 
      row = inflater.inflate(mlayoutResourceId, parent, false); 

      holder = new WeatherHolder(row); 


      row.setTag(holder); 

     } 
     else 
     { 
      holder = (WeatherHolder)row.getTag(); 
     } 

     weather w = mdata[position]; 
     holder.txtTitle.setText(w.mtitle); 
     holder.imgIcon.setImageResource(w.micon); 

     return row; 
    } 

WeatherHolder.java

class WeatherHolder 
    { 
     ImageView imgIcon; 
     TextView txtTitle; 


    public WeatherHolder(View v){ 

      imgIcon = (ImageView)row.findViewById(R.id.imgIcon); 
      txtTitle = (TextView)row.findViewById(R.id.txtTitle); 

    } 
    } 
} 

我看到的SO和其他許多答案網站和我瞭解listview的回收機制。

我也理解,從視圖中,我們可以在適配器中容納子視圖,我們不必多次調用findViewById()。所以,這是爲了優化。

但我只在setTag(holder)getTag()方法混淆。 From this question,我開始知道它是用於在多個對象上創建鍵值對,以便我們可以輕鬆訪問它們。但是,我不明白他們爲什麼需要在這裏...因爲我們沒有多個持有者對象......只有我們每次都必須更改持有者的變量。我們可以在這裏編碼而不使用setTaggetTag

任何人都可以更好地解釋什麼setTaggetTag做「這裏」?

+0

請不要標記爲重複...我已經看到這麼多的答案,但無法找到特定情況下的權利。 – xyz 2014-09-22 04:25:11

+1

爲什麼不試試你的方式,看看結果是什麼? – panini 2014-09-22 04:35:11

+0

我已經試過...我沒有問任何問題沒有試過..如果你知道,那麼請給出答案 – xyz 2014-09-22 04:37:53

回答

21

tag是一種機制,使views記住一些東西,可能是objectintegerstring或任何你喜歡的東西。

因此,當您的ListView將首次創建您的convertViewnull。因此您創建了一個新的convertView並將該的objects的所有references放在viewHolder中。然後將您的viewHolder保存到convertView的內存中(setTag)。 Android需要您的convertView並將其置於其poolrecycle它和passes它再次給你。但其pool可能沒有足夠的convertViews,因此它再次通過一個新的convertViewnull。所以故事重複,直到androidpool被填滿。之後android從其池中取出convertView並將其傳遞給您。你會發現它不是null,所以你問我第一次給你的物品references在哪裏? (getTag)所以你會得到這些,做你喜歡的任何事情。下面一行

but its pool may not have enough convertViews so it again passes a new convertView thats null

的Android pool

更多的闡述是當你listView將創建空的。因此對於您的listView的第一項,它會向您發送convertView,必須顯示。之後android將其保存在其pool中,因此其pool現在只包含一個convertView。對於你的第二項你的listView是要創建android不能使用它的池,因爲它實際上有一個元素,該元素是你的第一個項目,它現在正在顯示,所以它必須通過另一個convertView。這個過程重複,直到android在其pool中找到convertView那個現在沒有被顯示並傳遞給你。

當您滾動列表中使用的持有者時,Android會膨脹每行直到屏幕顯示爲止。

+0

謝謝,但我coudn't明白這一點:「但其池可能沒有足夠的convertViews,因此它再次通過一個新的convertView它是null」 - 那麼在這種情況下,它可能沒有足夠的convertviews? – xyz 2014-09-22 05:17:06

+0

更新它看看它再次 – mmlooloo 2014-09-22 05:32:18

+0

謝謝...簡而言之,Android必須膨脹新行的佈局,直到佈局適合屏幕尺寸。比使用持有者更改行內的子視圖之後。對? – xyz 2014-09-22 12:42:25

2

但是,我不明白爲什麼在這裏需要他們......因爲,我們沒有多座對象

這就是你不對的地方 - 有按次一個支架(又名可見或緩存的ListView條目)。

+0

你可以更詳細地解釋一下嗎? – xyz 2014-09-22 04:28:43

+1

每個視圖都有一個單獨的'WeatherHolder持有人'。 – 2014-09-22 04:31:43

+0

@ShivamVerma你的意思是 - 每一行。對? – xyz 2014-09-22 04:36:15

14

讓我們來看看在不同的角度:

enter image description here

讓我們想象直升機是 「行」,而是 「setTag」 和下面是「WeatherHolder」,但直升機的駕駛員是在那輛車裏,他/她是一個管理控制的人使用「WIRED REMOTE」直升機直升飛機。

當你切斷繩索即「setTag」時,直升機仍然飛行,但飛行員無法控制它,因爲飛行員落在地面上,這意味着飛行員已經死亡! (在Java中,當對象丟失引用時,垃圾收集器將收集該內容並從內存中釋放)。

當直升機即將飛到駕駛員所坐的地方時,如果您沒有將繩子放在車上或將其附着在車上 - 您可能會因爲使用「有線遙控器」而失去對直升機的控制權。

我希望這有助於:)。

相關問題