自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Android 自定義 BaseAdapter 最佳實(shí)踐

移動(dòng)開發(fā) Android
雖然現(xiàn)在很多新的項(xiàng)目都在使用RecyclerView,但是很多開發(fā)者在一些場(chǎng)景中還是傾向使用ListView或者GridView,然后就是需要寫許多的Adapter。

雖然現(xiàn)在很多新的項(xiàng)目都在使用RecyclerView,但是很多開發(fā)者在一些場(chǎng)景中還是傾向使用ListView或者GridView,然后就是需要寫許多的Adapter。一次項(xiàng)目組在新啟動(dòng)一個(gè)新項(xiàng)目的時(shí)候,有個(gè)同事拿來了一個(gè)網(wǎng)上說的***Adapter,在使用的時(shí)候發(fā)現(xiàn)即使在單個(gè)視圖類型一旦邏輯判斷比較復(fù)雜情況下非常不方便,更不用說在適配器Adapter中使用多視圖類型了,這里僅是個(gè)人觀點(diǎn),也許沒有掌握到精華。

[[191680]]

當(dāng)然了隨著RecyclerView的使用,網(wǎng)上也有很多有關(guān)對(duì)RecyclerView多視圖類型Adapter封裝的博客,MultiType 3.0是一個(gè)大神寫的比較全面的Adapter,***適配器Adapter自己使用不是很方便,于是就參看RecyclerView中Adapter的實(shí)現(xiàn)方式進(jìn)行對(duì)BaseAdapter進(jìn)行了簡單的封裝,封裝的目一是為了少寫代碼,另外一個(gè)就是讓邏輯看上去更清晰一些。我們知道在RecyclerView的Adapter實(shí)現(xiàn)中它將視圖創(chuàng)建與數(shù)據(jù)綁定進(jìn)行了分離,同時(shí)將對(duì)View的查找創(chuàng)建也剝離開來了,本文就主要介紹如何將BaseAdapter的使用封裝為跟RecyclerView的Adapter使用方式一致。由于很多時(shí)候在Adapter中我們都是使用的簡單的視圖類型,即單類型視圖,因此本文將單視圖類型的Adapter單獨(dú)封裝了一下,比使用多視圖類型的Adapter使用了更嚴(yán)格的數(shù)據(jù)類型檢查,同時(shí)在使用上也方便了許多。

 

[[191681]]

RecyclerView中Adapter的使用

在使用RecyclerView的Adapter的時(shí)候我們首先需要繼承RecyclerView的一個(gè)靜態(tài)內(nèi)部類Adapter,然后重寫三個(gè)方法,實(shí)際上下面三個(gè)方法是必須要重寫的,因?yàn)槎际浅橄蠓椒ā?/p>

  • getItemCount()
  • onBindViewHolder(VH holder, int position)
  • onCreateViewHolder(ViewGroup parent, int viewType)

一般情況下重寫上面三個(gè)方法就可以,但是如果存在多視圖類型,在第三個(gè)方法

onCreateViewHolder()方法中我們也可以看到有一個(gè)參數(shù)是viewType,該參數(shù)作用就是針對(duì)不同的viewType需要?jiǎng)?chuàng)建不同的ViewHolder,因此還需要重寫一個(gè)方法getItemViewType(int position),針對(duì)多視圖類型同BaseAdapter實(shí)現(xiàn)方式倒是很像,在BaseAdapter中這是需要除此之外還要重寫一個(gè)方法getViewTypeCount(),但是在RecyclerView的Adapter中不需要該方法。

簡單類型Adapter

  1. private class MyAdapter extends RecyclerView.Adapter<MyViewHolder> { 
  2.  
  3.     @Override 
  4.     public int getItemCount() { 
  5.         return COUNT
  6.     } 
  7.  
  8.     @Override 
  9.     public void onBindViewHolder(MyViewHolder holder, int position) { 
  10.         holder.textView.setText("TEXT_" + position); 
  11.     } 
  12.  
  13.     @Override 
  14.     public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
  15.         View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.item_text, parent, false); 
  16.         MyViewHolder holder = new MyViewHolder(view); 
  17.         return holder; 
  18.     } 
  19.  
  20.  
  21. private static class MyViewHolder extends RecyclerView.ViewHolder { 
  22.     private TextView textView; 
  23.  
  24.     public MyViewHolder(View itemView) { 
  25.         super(itemView); 
  26.         textView = (TextView) itemView.findViewById(R.id.textView); 
  27.     } 

復(fù)雜類型Adapter

  1. private class MyAdapter extends RecyclerView.Adapter<ViewHolder> { 
  2.  
  3.     @Override 
  4.     public int getItemCount() { 
  5.         return COUNT
  6.     } 
  7.  
  8.     @Override 
  9.     public int getItemViewType(int position) { 
  10.         return position % 2 == 0 ? TYPE_IMAGE : TYPE_TEXT; 
  11.     } 
  12.  
  13.     @Override 
  14.     public void onBindViewHolder(ViewHolder holder, int position) { 
  15.         int type = getItemViewType(position); 
  16.         switch (type) { 
  17.         case TYPE_TEXT: 
  18.             ((MyTextHolder) holder).textView.setText("TEXT_" + position); 
  19.             break; 
  20.         case TYPE_IMAGE: 
  21.             ((MyImageHolder) holder).imageView.setImageResource(R.drawable.image); 
  22.             break; 
  23.         } 
  24.     } 
  25.  
  26.     @Override 
  27.     public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
  28.         View view
  29.         ViewHolder holder = null
  30.         switch (viewType) { 
  31.         case TYPE_TEXT: 
  32.             view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.item_text, parent, false); 
  33.             holder = new MyTextHolder(view); 
  34.             break; 
  35.         case TYPE_IMAGE: 
  36.             view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.item_image, parent, false); 
  37.             holder = new MyImageHolder(view); 
  38.             break; 
  39.         } 
  40.         return holder; 
  41.     } 
  42.  
  43. private class MyTextHolder extends RecyclerView.ViewHolder { 
  44.     private TextView textView; 
  45.  
  46.     public MyTextHolder(View itemView) { 
  47.         super(itemView); 
  48.         textView = (TextView) itemView.findViewById(R.id.textView); 
  49.     } 
  50.  
  51. private class MyImageHolder extends ViewHolder { 
  52.     private ImageView imageView; 
  53.  
  54.     public MyImageHolder(View itemView) { 
  55.         super(itemView); 
  56.         imageView = (ImageView) itemView.findViewById(R.id.imageView); 
  57.     } 

自定義BaseAdapter

在自定義基類之前,先簡單分析一下,我們需要自定義一個(gè)支持單種視圖的Adapter,還要自定義一個(gè)支持多種視圖類型的Adapter,兩個(gè)類都要繼承BaseAdapter,先將兩個(gè)類都公用的部分抽取出來定義為MyAdapter。

  1. public abstract class MyAdapter<T> extends BaseAdapter { 
  2.  
  3.     protected List<T> dataList = new ArrayList<>(); 
  4.     protected Context context; 
  5.     protected LayoutInflater inflater; 
  6.  
  7.     public MyAdapter(Context context) { 
  8.         this.context = context; 
  9.         inflater = LayoutInflater.from(context); 
  10.     } 
  11.  
  12.     public void setDataList(List<T> dataList) { 
  13.         this.dataList = dataList; 
  14.         notifyDataSetChanged(); 
  15.     } 
  16.  
  17.     @Override 
  18.     public int getCount() { 
  19.         if (null == dataList) { 
  20.             return 0; 
  21.         } 
  22.         return dataList.size(); 
  23.     } 
  24.  
  25.     @Override 
  26.     public T getItem(int position) { 
  27.         return dataList.get(position); 
  28.     } 
  29.  
  30.     @Override 
  31.     public long getItemId(int position) { 
  32.         return position; 
  33.     } 
  34.  

在RecyclerView的Adapter實(shí)現(xiàn)中是沒有g(shù)etView()方法的,下面我們就分析一下getView()方法如何拆分,一般情況下我們?cè)趯?shí)現(xiàn)getView()方法都是如下流程。

  1. public View getView(int position, View convertView, ViewGroup parent) { 
  2.     ViewHolder holder = null
  3.     if (null == convertView) { 
  4.         //填充布局 
  5.         convertView=inflater.inflate(R.layout.item_layout, parent,false); 
  6.         holder = new ViewHolder(); 
  7.         //通過ID查詢控件 
  8.         holder.textView=(TextView)convertView.findViewById(R.id.textView); 
  9.         holder.imageView=(ImageView)convertView.findViewById(R.id.imageView); 
  10.         convertView .setTag(holder); 
  11.     } else { 
  12.         holder = (ViewHolder) convertView.getTag(); 
  13.     } 
  14.     //賦值邏輯 
  15.     return convertView; 
  16. //一個(gè)空的ViewHolder 
  17. public static class ViewHolder{ 
  18.     TextView textView; 
  19.     ImageView imageView; 

Java編程比較流行的一種編程方式不是說面向接口編程嗎,在Android開發(fā)中也有一個(gè)開發(fā)方式叫做面向Holder的編程,上面代碼是傳統(tǒng)的實(shí)現(xiàn)ViewHolder的方式,說句實(shí)現(xiàn)話就沒做什么事,就是作為一個(gè)載體承載著我們需要的控件。我們讓ViewHolder多做一些事情,讓它在convertView==null情況下需要做的多數(shù)邏輯都放到ViewHolder中去。

  1. public class ViewHolder { 
  2.     private final View itemView; 
  3.  
  4.     public ViewHolder(View itemView) { 
  5.         if (null == itemView) { 
  6.             throw new IllegalArgumentException("itemView must not be null"); 
  7.         } else { 
  8.             this.itemView = itemView; 
  9.             itemView.setTag(this); 
  10.         } 
  11.     } 
  12.  
  13.     public View getItemView() { 
  14.         return itemView; 
  15.     } 

在ViewHolder中的itemView就是getView()方法中的convertView,這里剛好是條目的根View,類似RecyclerView中ViewHolder構(gòu)造方法中itemView。由于不同的視圖需要?jiǎng)?chuàng)建不同的ViewHolder,因此我們可以將創(chuàng)建ViewHolder的方法設(shè)置為抽象的方法暴露出去,另外賦值的時(shí)候我們也需要根據(jù)具體的業(yè)務(wù)進(jìn)行賦值,同樣設(shè)置一個(gè)抽象方法。

  1. public abstract class SimpleAdapter<T,VH extends ViewHolder> extends MyAdapter<T> { 
  2.  
  3.     public SimpleAdapter(Context context) { 
  4.         super(context); 
  5.     } 
  6.  
  7.     public View getView(int position, View convertView, ViewGroup parent) { 
  8.         VH holder = null
  9.         if (null == convertView) { 
  10.             holder = onCreateViewHolder(parent); 
  11.             convertView = holder.getItemView(); 
  12.         } else { 
  13.             holder = (VH) convertView.getTag(); 
  14.         } 
  15.         onBindViewHolder(holder, position); 
  16.         return convertView; 
  17.     } 
  18.  
  19.     public abstract void onBindViewHolder(VH holder, int position); 
  20.  
  21.     public abstract VH onCreateViewHolder(ViewGroup parent); 
  22.  

在設(shè)置多視圖類型的Adapter的時(shí)候只需要在創(chuàng)建ViewHolder的時(shí)候多傳入一個(gè)viewType的參數(shù)即可。

  1. public abstract class MultiAdapter<T> extends MyAdapter<T> { 
  2.  
  3.     public MultiAdapter(Context context) { 
  4.         super(context); 
  5.     } 
  6.  
  7.     @Override 
  8.     public View getView(int position, View convertView, ViewGroup parent) { 
  9.         ViewHolder holder = null
  10.         if (null == convertView) { 
  11.             holder = onCreateViewHolder(parent, getItemViewType(position)); 
  12.             convertView = holder.getItemView(); 
  13.         } else { 
  14.             holder = (ViewHolder) convertView.getTag(); 
  15.         } 
  16.         onBindViewHolder(holder, position); 
  17.         return convertView; 
  18.     } 
  19.  
  20.     public abstract void onBindViewHolder(ViewHolder holder, int position); 
  21.  
  22.     public abstract ViewHolder onCreateViewHolder(ViewGroup parent, int viewType); 
  23.  

自定義BaseAdapter的使用

單視圖類型SimpleAdapter使用

  1. public class TextAdapter extends SimpleAdapter<String, TextAdapter.TextHolder> { 
  2.  
  3.     public TextAdapter(Context context) { 
  4.         super(context); 
  5.     } 
  6.  
  7.     @Override 
  8.     public void onBindViewHolder(TextHolder holder, int position) { 
  9.         holder.textView.setText(getItem(position)); 
  10.     } 
  11.  
  12.     @Override 
  13.     public TextHolder onCreateViewHolder(ViewGroup parent) { 
  14.         View convertView=inflater.inflate(R.layout.item_text, parent, false); 
  15.         return new TextHolder(convertView); 
  16.     } 
  17.  
  18.     static class TextHolder extends ViewHolder{ 
  19.  
  20.         public TextView textView; 
  21.  
  22.         public TextHolder(View itemView) { 
  23.             super(itemView); 
  24.             textView=(TextView) itemView.findViewById(R.id.textView); 
  25.         } 
  26.     } 

這里我們使用了兩個(gè)泛型,一個(gè)是ViewHolder中支持的數(shù)據(jù)類型String,另外一個(gè)就是我們需要?jiǎng)?chuàng)建的ViewHolder,這樣在onCreateViewHolder方法的返回值就會(huì)自動(dòng)返回我們自定義的ViewHolder,有關(guān)泛型更多的知識(shí)可以參看Java泛型使用解析,單視圖類型Adapter的使用比RecyclerView的Adapter還要方便許多。

多視圖類型的使用

  1. public class RichAdapter extends MultiAdapter<String> { 
  2.  
  3.     private static final int TEXT = 0; 
  4.     private static final int PIC = 1; 
  5.  
  6.     public RichAdapter(Context context) { 
  7.         super(context); 
  8.     } 
  9.  
  10.     @Override 
  11.     public int getViewTypeCount() { 
  12.         return 2; 
  13.     } 
  14.  
  15.     @Override 
  16.     public int getItemViewType(int position) { 
  17.         if (position % 3 == 0) { 
  18.             return PIC; 
  19.         } else { 
  20.             return TEXT; 
  21.         } 
  22.     } 
  23.  
  24.     @Override 
  25.     public void onBindViewHolder(ViewHolder holder, int position) { 
  26.         switch (getItemViewType(position)) { 
  27.         case TEXT: 
  28.             TextHolder textHolder=(TextHolder) holder; 
  29.             textHolder.textView.setText(getItem(position)); 
  30.             break; 
  31.         case PIC: 
  32.             ImageHolder imageHolder=(ImageHolder) holder; 
  33.             imageHolder.imageView.setImageResource(R.drawable.image); 
  34.             break; 
  35.         } 
  36.     } 
  37.  
  38.     @Override 
  39.     public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
  40.         View itemView = null
  41.         ViewHolder holder = null
  42.         switch (viewType) { 
  43.         case TEXT: 
  44.             itemView = inflater.inflate(R.layout.item_text, parent, false); 
  45.             holder = new TextHolder(itemView); 
  46.             break; 
  47.         case PIC: 
  48.             itemView = inflater.inflate(R.layout.item_image, parent, false); 
  49.             holder = new ImageHolder(itemView); 
  50.             break; 
  51.         } 
  52.         return holder; 
  53.     } 
  54.  
  55.     private static class TextHolder extends ViewHolder { 
  56.         TextView textView; 
  57.  
  58.         public TextHolder(View itemView) { 
  59.             super(itemView); 
  60.             textView = (TextView) itemView.findViewById(R.id.textView); 
  61.         } 
  62.  
  63.     } 
  64.  
  65.     private static class ImageHolder extends ViewHolder { 
  66.         ImageView imageView; 
  67.  
  68.         public ImageHolder(View itemView) { 
  69.             super(itemView); 
  70.             imageView = (ImageView) itemView.findViewById(R.id.imageView); 
  71.         } 
  72.     } 

這里的使用情況跟RecyclerView的使用幾乎是一模一樣,唯一不一樣的地方就是多寫了一個(gè)getViewTypeCount()方法,在ListView或者GridView使用BaseAdapter實(shí)現(xiàn)多種類型視圖的時(shí)候該方法必須要重寫。

責(zé)任編輯:武曉燕 來源: 碼農(nóng)網(wǎng)
相關(guān)推薦

2017-05-18 12:36:16

android萬能適配器列表視圖

2010-08-12 09:45:33

jQuery自定義事件

2016-11-16 21:55:55

源碼分析自定義view androi

2023-12-21 09:00:21

函數(shù)React 組件useEffect

2016-12-26 15:25:59

Android自定義View

2025-01-22 11:10:34

2013-04-01 14:35:10

Android開發(fā)Android自定義x

2010-02-07 14:02:16

Android 界面

2016-04-12 10:07:55

AndroidViewList

2023-06-27 15:02:47

2023-06-28 08:05:46

場(chǎng)景vue3自定義

2013-05-02 14:08:18

2014-12-10 10:37:45

Android自定義布局

2015-02-11 17:49:35

Android源碼自定義控件

2014-12-17 09:46:30

AndroidListView最佳實(shí)踐

2013-01-09 17:22:38

Android開發(fā)Camera

2015-02-12 15:33:43

微信SDK

2018-09-28 05:18:41

2015-02-12 15:38:26

微信SDK

2013-05-20 17:48:20

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)