閱讀32 返回首頁    go 阿裏雲 go 技術社區[雲棲]


ViewHolder模式超簡潔寫法,很cool!

轉自https://www.eoeandroid.com/forum.php?mod=viewthread&tid=321547&page=3#pid3555274



ViewHolder是什麼就不解釋了。

        大家通常怎麼寫ViewHolder呢?
01         ViewHolder holder =null;
02         if(convertView ==null){
03                 convertView = mInflater.inflate(R.layout.xxxnull);
04                 holder =new ViewHolder();
05                 holder.tvXXX = (TextView)findViewById(R.id.xxx);
06                 //...一連串的findViewById
07         }
08         else{
09                 holder = (ViewHolder) convertView.getTag();  
10         }
11          
12          
13          
14         privatestatic class ViewHolder{
15                 TextView tvXXX;
16                 //很多view的定義
17         }



      這麼寫一次還行,但問題是總有很多很多的ViewAdapter要這麼寫,每次都repeat,repeat,repeat  累啊。      所以,有這麼一種簡潔的寫法分享給大家,先聲明,從國外網站上看的,不是自己原創的,但確實很喜歡這個簡潔的設計。

ViewHolder這麼寫(隻提供一個靜態方法,其實可以加一個私有構造函數防止外部實例化),代碼很簡單,看過就明白了
01 public classViewHolder {
02     // I added a generic return type to reduce the casting noise in client code
03     @SuppressWarnings("unchecked")
04     publicstatic <T extendsView> T get(View view, intid) {
05         SparseArray<View> viewHolder = (SparseArray<View>) view.getTag();
06         if(viewHolder == null) {
07             viewHolder =new SparseArray<View>();
08             view.setTag(viewHolder);
09         }
10         View childView = viewHolder.get(id);
11         if(childView == null) {
12             childView = view.findViewById(id);
13             viewHolder.put(id, childView);
14         }
15         return(T) childView;
16     }
17 }



在getView裏這樣
01 @Override
02 public View getView(intposition, View convertView, ViewGroup parent) {
03  
04     if(convertView == null) {
05         convertView = LayoutInflater.from(context)
06           .inflate(R.layout.banana_phone, parent,false);
07     }
08  
09     ImageView bananaView = ViewHolder.get(convertView, R.id.banana);
10     TextView phoneView = ViewHolder.get(convertView, R.id.phone);
11  
12     BananaPhone bananaPhone = getItem(position);
13     phoneView.setText(bananaPhone.getPhone());
14     bananaView.setImageResource(bananaPhone.getBanana());
15  
16     returnconvertView;
17 }



        哈哈,完成了,果斷把這個ViewHolder類加入自己的utils,一勞永逸了以後~

        值得注意的是SparseArray這個知識點,優化過的存儲integer和object鍵值對的hashmap,網上資料很多這裏就不廢話了~




其實這種寫法本質和ViewHolder Partten沒有什麼不同,ViewHolder Partten是把一個自定義類綁定到一個view,這種是把SparseArray綁定到一個view,雖然SparseArray 初始化會分配10長度的地址,理論上貌似浪費了內存,理論上插入和刪除操作也是有時間損耗的,但是這些都在允許範圍內。

比如https://github.com/JoanZapata/base-adapter-helper 作者也說了他做了大量測試,這種損耗微乎其微。

再次,萬一萬一因特殊情況發現了有性能瓶頸,到時候再優化就可以了,但是絕大多數場合都是可以使用的,大量簡化你的開發,加快開發速度,代碼少了,出錯的幾率就小了,維護的成本也小了~好處還是大大的。



簡單的紙上分析~:
(1)ViewHolder Pattern是每一個View一個ViewHolder,裏麵是記錄listitem內控件引用; SparseArray是記錄id和控件引用的鍵值對,當然SparseArray初始化會分配一定地址空間(默認是10),但是這些內存損耗應該是可以忽略的~
(2)SparseArray是優化過的int-object的hashmap,使用折半查找,並優化了內存分配,所以代碼執行成本通常是可控的。

綜上,使用SparseArray與ViewHolder相比是有損耗,但應該是可控的。使用SparseArray優點是加快開發速度和減少代碼維護,當發現有性能瓶頸時,再進行優化~


最後更新:2017-04-03 06:03:03

  上一篇:go Oracle 常用命令小結
  下一篇:go Oracle 常用命令小結