Android中适用于ListView、GridView等组件的通用Adapter

今天随便逛逛CSDN,看到主页上推荐了一篇文章Android 快速开发系列 打造万能的ListView GridView 适配器,刚好这两天写项目自己也封装了类似的CommonAdapter,以前也在github上看到过这样的库,于是自己也把自己的代码再次整理出来与大家分享,也希望能够在CSDN这个平台上学到更多的东西,下面就一起来看看吧。

    平时我们在项目中使用到ListView和GridView组件都是都会用到Adapter,比较多的情况是继承自BaseAdapter,然后实现getCount、getView等方法,再使用ViewHolder来提高一下效率.我们看下面一个简单的例子 :

ListView布局文件

fragment_main.xml :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.push_demo_1.MainActivity$PlaceholderFragment" >

    <ListView
        android:id="@+id/my_listview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

ListView子项的布局文件

listview_item_layout.xml :

[html]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent"  
  5.     android:orientation="horizontal" >  
  6.   
  7.     <ImageView  
  8.         android:id="@+id/my_imageview"  
  9.         android:layout_width="64dp"  
  10.         android:layout_height="64dp"  
  11.         android:contentDescription="@string/app_name" />  
  12.   
  13.     <TextView  
  14.         android:id="@+id/my_textview"  
  15.         android:layout_width="wrap_content"  
  16.         android:layout_height="wrap_content"  
  17.         android:layout_marginLeft="20dp"  
  18.         android:textSize="18sp" />  
  19.   
  20. </LinearLayout>  

曾经我们要写下的Adapter代码

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public class NormalAdapter extends BaseAdapter {  
  2.   
  3.     Context mContext;  
  4.   
  5.     LayoutInflater mInflater;  
  6.   
  7.     List<ListViewItem> mDataList;  
  8.   
  9.     /** 
  10.      * @param context 
  11.      * @param data 
  12.      */  
  13.     public NormalAdapter(Context context, List<ListViewItem> data) {  
  14.         mContext = context;  
  15.         mInflater = LayoutInflater.from(context);  
  16.         mDataList = data;  
  17.     }  
  18.   
  19.     @Override  
  20.     public int getCount() {  
  21.         return mDataList.size();  
  22.     }  
  23.   
  24.     @Override  
  25.     public ListViewItem getItem(int position) {  
  26.         return mDataList.get(position);  
  27.     }  
  28.   
  29.     @Override  
  30.     public long getItemId(int position) {  
  31.         return position;  
  32.     }  
  33.   
  34.     @Override  
  35.     public View getView(int position, View convertView, ViewGroup parent) {  
  36.         ViewHolder viewHolder = null;  
  37.         if (convertView == null) {  
  38.             convertView = mInflater.inflate(R.layout.listview_item_layout, nullfalse);  
  39.             viewHolder = new ViewHolder();  
  40.             viewHolder.mImageView = (ImageView) convertView.findViewById(R.id.my_imageview);  
  41.             viewHolder.mTextView = (TextView) convertView.findViewById(R.id.my_textview);  
  42.             convertView.setTag(viewHolder);  
  43.         } else {  
  44.             viewHolder = (ViewHolder) convertView.getTag();  
  45.         }  
  46.   
  47.         viewHolder.mImageView.setImageResource(getItem(position).mDrawableId);  
  48.         viewHolder.mTextView.setText(getItem(position).mText);  
  49.         return convertView;  
  50.     }  
  51.   
  52.     /** 
  53.      * ViewHolder 
  54.      *  
  55.      * @author mrsimple 
  56.      */  
  57.     static class ViewHolder {  
  58.         ImageView mImageView;  
  59.         TextView mTextView;  
  60.     }  
  61.   
  62. }  

    然而写过多遍以后我们发现我们总是重复地在写这些getCount、getItem、getView方法以及ViewHolder,导致了很多重复工作,而且及其无聊,于是我把这些重复工作抽象起来(以前也有在github上看到这样的通用Adapter实现),整理一下也便于自己使用,也是自己学习的一个过程。下面我们看看使用CommonAdapter后我们做与上面同样的工作需要怎么写。

使用CommonAdapter后要写的代码

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. CommonAdapter<ListViewItem> listAdapter = new CommonAdapter<ListViewItem>(getActivity(),  
  2.                     R.layout.listview_item_layout, mockListViewItems()) {  
  3.   
  4.                 @Override  
  5.                 protected void fillItemData(CommonViewHolder viewHolder, ListViewItem item) {  
  6.                     // 设置图片  
  7.                     viewHolder.setImageForView(R.id.my_imageview, item.mDrawableId);  
  8.                     // 设置text  
  9.                     viewHolder.setTextForTextView(R.id.my_textview, item.mText);  
  10.                 }  
  11.             }  

其中mockListViewImtes是准备了一些数据, 代码如下 : 
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 模拟一些数据 
  3.  *  
  4.  * @return 
  5.  */  
  6. private List<ListViewItem> mockListViewItems() {  
  7.     List<ListViewItem> dataItems = new ArrayList<ListViewItem>();  
  8.     dataItems.add(new ListViewItem(R.drawable.girl_96, "girl_96.png"));  
  9.     dataItems.add(new ListViewItem(R.drawable.fire_96, "fire_96.png"));  
  10.     dataItems.add(new ListViewItem(R.drawable.grimace_96, "grimace_96.png"));  
  11.     dataItems.add(new ListViewItem(R.drawable.laugh_96, "laugh_96.png"));  
  12.     return dataItems;  
  13. }  

可以看到,我们的代码量减少了很多,如果一个项目中有好几个ListView、GridView等组件,我们就不需要重复做那么多无聊的工作了。我们看看效果图 : 


CommonAdapter实现

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 
  3.  *  created by Mr.Simple, Aug 28, 201412:26:52 PM. 
  4.  *  Copyright (c) 2014, hehonghui@umeng.com All Rights Reserved. 
  5.  * 
  6.  *                ##################################################### 
  7.  *                #                                                   # 
  8.  *                #                       _oo0oo_                     #    
  9.  *                #                      o8888888o                    # 
  10.  *                #                      88" . "88                    # 
  11.  *                #                      (| -_- |)                    # 
  12.  *                #                      0\  =  /0                    #    
  13.  *                #                    ___/`---'\___                  # 
  14.  *                #                  .' \\|     |# '.                 # 
  15.  *                #                 / \\|||  :  |||# \                # 
  16.  *                #                / _||||| -:- |||||- \              # 
  17.  *                #               |   | \\\  -  #/ |   |              # 
  18.  *                #               | \_|  ''\---/''  |_/ |             # 
  19.  *                #               \  .-\__  '-'  ___/-. /             # 
  20.  *                #             ___'. .'  /--.--\  `. .'___           # 
  21.  *                #          ."" '<  `.___\_<|>_/___.' >' "".         # 
  22.  *                #         | | :  `- \`.;`\ _ /`;.`/ - ` : | |       # 
  23.  *                #         \  \ `_.   \_ __\ /__ _/   .-` /  /       # 
  24.  *                #     =====`-.____`.___ \_____/___.-`___.-'=====    # 
  25.  *                #                       `=---='                     # 
  26.  *                #     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   # 
  27.  *                #                                                   # 
  28.  *                #               佛祖保佑         永无BUG              # 
  29.  *                #                                                   # 
  30.  *                ##################################################### 
  31.  */  
  32.   
  33. package com.uit.commons;  
  34.   
  35. import android.content.Context;  
  36. import android.view.View;  
  37. import android.view.ViewGroup;  
  38. import android.widget.BaseAdapter;  
  39.   
  40. import java.util.List;  
  41.   
  42. /** 
  43.  * 这是一个通用、抽象的适配器类,覆写了BaseAdapter的getCount, getItem, getItemId, 
  44.  * getView方法,在getView方法中通过 
  45.  * 通用的CommonViewHolder来对convertView的进行处理,并且缓存convertView中的其他View元素 
  46.  * ,降低了ListView、GridView 等组件的Adapter和ViewHolder的代码量. 
  47.  * 用户只需要在fillItemData函数中将第position位置里的数据填充到listview或者gridview的第position的view中即可 
  48.  * ,具体使用实例参考文档. 
  49.  *  
  50.  * @author mrsimple 
  51.  * @param <T> 数据源的类型 
  52.  */  
  53. public abstract class CommonAdapter<T> extends BaseAdapter {  
  54.   
  55.     /** 
  56.      * Context 
  57.      */  
  58.     Context mContext;  
  59.     /** 
  60.      * 要展示的数据列表 
  61.      */  
  62.     List<T> mData;  
  63.     /** 
  64.      * 每一项的布局id,例如R.layout.my_listview_item. 
  65.      */  
  66.     private int mItemLayoutId = -1;  
  67.   
  68.     /** 
  69.      * @param context Context 
  70.      * @param itemLayoutResId 
  71.      *            每一项(适用于listview、gridview等AbsListView子类)的布局资源id,例如R.layout. 
  72.      *            my_listview_item. 
  73.      * @param dataSource 数据源 
  74.      */  
  75.     public CommonAdapter(Context context, int itemLayoutResId, List<T> dataSource) {  
  76.         checkParams(context, itemLayoutResId, dataSource);  
  77.         mContext = context;  
  78.         mItemLayoutId = itemLayoutResId;  
  79.         mData = dataSource;  
  80.     }  
  81.   
  82.     /** 
  83.      * 检查参数的有效性 
  84.      *  
  85.      * @param context 
  86.      * @param itemLayoutResId 
  87.      * @param dataSource 
  88.      */  
  89.     private void checkParams(Context context, int itemLayoutResId, List<T> dataSource) {  
  90.         if (context == null || itemLayoutResId < 0 || dataSource == null) {  
  91.             throw new RuntimeException(  
  92.                     "context == null || itemLayoutResId < 0 || dataSource == null, please check your params");  
  93.         }  
  94.     }  
  95.   
  96.     /** 
  97.      * 返回数据的总数 
  98.      */  
  99.     @Override  
  100.     public int getCount() {  
  101.         return mData.size();  
  102.     }  
  103.   
  104.     /** 
  105.      * 返回position位置的数据 
  106.      */  
  107.     @Override  
  108.     public T getItem(int position) {  
  109.         return mData.get(position);  
  110.     }  
  111.   
  112.     /** 
  113.      * item id, 返回position 
  114.      */  
  115.     @Override  
  116.     public long getItemId(int position) {  
  117.         return position;  
  118.     }  
  119.   
  120.     /** 
  121.      * 返回position位置的view, 即listview、gridview的第postion个view 
  122.      */  
  123.     @Override  
  124.     public View getView(int position, View convertView, ViewGroup parent) {  
  125.         // 获取ViewHolder  
  126.         CommonViewHolder viewHolder = CommonViewHolder.getViewHolder(mContext, convertView,  
  127.                 mItemLayoutId);  
  128.         // 填充数据  
  129.         fillItemData(viewHolder, getItem(position));  
  130.         // 返回convertview  
  131.         return viewHolder.getConvertView();  
  132.     }  
  133.   
  134.     /** 
  135.      * 用户必须覆写该方法来讲数据填充到视图中 
  136.      *  
  137.      * @param viewHolder 通用的ViewHolder, 里面会装载listview, 
  138.      *            gridview等组件的每一项的视图,并且缓存其子view 
  139.      * @param item 数据源的第position项数据 
  140.      */  
  141.     protected abstract void fillItemData(CommonViewHolder viewHolder, T item);  
  142.   
  143. }  

CommonViewHolder实现

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * 
  3.  *  created by Mr.Simple, Aug 28, 201412:32:45 PM. 
  4.  *  Copyright (c) 2014, hehonghui@umeng.com All Rights Reserved. 
  5.  * 
  6.  *                ##################################################### 
  7.  *                #                                                   # 
  8.  *                #                       _oo0oo_                     #    
  9.  *                #                      o8888888o                    # 
  10.  *                #                      88" . "88                    # 
  11.  *                #                      (| -_- |)                    # 
  12.  *                #                      0\  =  /0                    #    
  13.  *                #                    ___/`---'\___                  # 
  14.  *                #                  .' \\|     |# '.                 # 
  15.  *                #                 / \\|||  :  |||# \                # 
  16.  *                #                / _||||| -:- |||||- \              # 
  17.  *                #               |   | \\\  -  #/ |   |              # 
  18.  *                #               | \_|  ''\---/''  |_/ |             # 
  19.  *                #               \  .-\__  '-'  ___/-. /             # 
  20.  *                #             ___'. .'  /--.--\  `. .'___           # 
  21.  *                #          ."" '<  `.___\_<|>_/___.' >' "".         # 
  22.  *                #         | | :  `- \`.;`\ _ /`;.`/ - ` : | |       # 
  23.  *                #         \  \ `_.   \_ __\ /__ _/   .-` /  /       # 
  24.  *                #     =====`-.____`.___ \_____/___.-`___.-'=====    # 
  25.  *                #                       `=---='                     # 
  26.  *                #     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~   # 
  27.  *                #                                                   # 
  28.  *                #               佛祖保佑         永无BUG              # 
  29.  *                #                                                   # 
  30.  *                ##################################################### 
  31.  */  
  32.   
  33. package com.uit.commons;  
  34.   
  35. import android.content.Context;  
  36. import android.graphics.Bitmap;  
  37. import android.view.View;  
  38. import android.widget.CheckBox;  
  39. import android.widget.ImageView;  
  40. import android.widget.TextView;  
  41.   
  42. import com.uit.commons.utils.ViewFinder;  
  43.   
  44. /** 
  45.  * 这是一个通用的ViewHolder, 将会装载AbsListView子类的item View, 并且将item 
  46.  * view中的子视图进行缓存和索引,使得用户能够方便的获取这些子view, 减少了代码重复。 
  47.  *  
  48.  * @author mrsimple 
  49.  */  
  50. public class CommonViewHolder {  
  51.   
  52.     /** 
  53.      * 构造函数 
  54.      *  
  55.      * @param context Context 
  56.      * @param layoutId ListView、GridView或者其他AbsListVew子类的 Item View的资源布局id 
  57.      */  
  58.     protected CommonViewHolder(Context context, int layoutId) {  
  59.         // 初始化布局, 装载ContentView  
  60.         ViewFinder.initContentView(context, layoutId);  
  61.         // 将ViewHolder存储在ContentView的tag中  
  62.         ViewFinder.getContentView().setTag(this);  
  63.     }  
  64.   
  65.     /** 
  66.      * 获取CommonViewHolder,当convertView为空的时候从布局xml装载item view, 
  67.      * 并且将该CommonViewHolder设置为convertView的tag, 便于复用convertView. 
  68.      *  
  69.      * @param context Context 
  70.      * @param convertView Item view 
  71.      * @param layoutId 布局资源id, 例如R.layout.my_listview_item. 
  72.      * @return 通用的CommonViewHolder实例 
  73.      */  
  74.     public static CommonViewHolder getViewHolder(Context context, View convertView, int layoutId) {  
  75.         if (convertView == null) {  
  76.             return new CommonViewHolder(context, layoutId);  
  77.         }  
  78.   
  79.         return (CommonViewHolder) convertView.getTag();  
  80.     }  
  81.   
  82.     /** 
  83.      * @return 当前项的convertView, 在构造函数中装载 
  84.      */  
  85.     public View getConvertView() {  
  86.         return ViewFinder.getContentView();  
  87.     }  
  88.   
  89.     /** 
  90.      * 为id为textViewId的TextView设置文本内容 
  91.      *  
  92.      * @param textViewId 视图id 
  93.      * @param text 要设置的文本内容 
  94.      */  
  95.     public void setTextForTextView(int textViewId, CharSequence text) {  
  96.         TextView textView = ViewFinder.findViewById(textViewId);  
  97.         if (textView != null) {  
  98.             textView.setText(text);  
  99.         }  
  100.     }  
  101.   
  102.     /** 
  103.      * 为ImageView设置图片 
  104.      *  
  105.      * @param imageViewId ImageView的id, 例如R.id.my_imageview 
  106.      * @param drawableId Drawable图片的id, 例如R.drawable.my_photo 
  107.      */  
  108.     public void setImageForView(int imageViewId, int drawableId) {  
  109.         ImageView imageView = ViewFinder.findViewById(imageViewId);  
  110.         if (imageView != null) {  
  111.             imageView.setImageResource(drawableId);  
  112.         }  
  113.     }  
  114.   
  115.     /** 
  116.      * 为ImageView设置图片 
  117.      *  
  118.      * @param imageViewId ImageView的id, 例如R.id.my_imageview 
  119.      * @param bmp Bitmap图片 
  120.      */  
  121.     public void setImageForView(int imageViewId, Bitmap bmp) {  
  122.         ImageView imageView = ViewFinder.findViewById(imageViewId);  
  123.         if (imageView != null) {  
  124.             imageView.setImageBitmap(bmp);  
  125.         }  
  126.     }  
  127.   
  128.     /** 
  129.      * 为CheckBox设置是否选中 
  130.      *  
  131.      * @param checkViewId CheckBox的id 
  132.      * @param isCheck 是否选中 
  133.      */  
  134.     public void setCheckForCheckBox(int checkViewId, boolean isCheck) {  
  135.         CheckBox checkBox = ViewFinder.findViewById(checkViewId);  
  136.         if (checkBox != null) {  
  137.             checkBox.setChecked(isCheck);  
  138.         }  
  139.     }  
  140. }  


ViewFinder辅助类

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * view finder, 方便查找View。用户需要在使用时调用initContentView, 
  3.  * 将Context和布局id传进来,然后使用findViewById来获取需要的view 
  4.  * ,findViewById为泛型方法,返回的view则直接是你接收的类型,而不需要进行强制类型转换.比如, 
  5.  * 以前我们在Activity中找一个TextView一般是这样 :  
  6.  * TextView textView = (TextView)findViewById(viewId);  
  7.  * 如果页面中的控件比较多,就会有很多的类型转换,而使用ViewFinder则免去了类型转换, 
  8.  * 示例如下 :  
  9.  * TextView textView = ViewFinder.findViewById(viewId); 
  10.  *  
  11.  * @author mrsimple 
  12.  */  
  13. public final class ViewFinder {  
  14.   
  15.     /** 
  16.      * LayoutInflater 
  17.      */  
  18.     static LayoutInflater mInflater;  
  19.   
  20.     /** 
  21.      * 每项的View的sub view Map 
  22.      */  
  23.     private static SparseArray<View> mViewMap = new SparseArray<View>();  
  24.   
  25.     /** 
  26.      * Content View 
  27.      */  
  28.     static View mContentView;  
  29.   
  30.     /** 
  31.      * 初始化ViewFinder, 实际上是获取到该页面的ContentView. 
  32.      *  
  33.      * @param context 
  34.      * @param layoutId 
  35.      */  
  36.     public static void initContentView(Context context, int layoutId) {  
  37.         mInflater = LayoutInflater.from(context);  
  38.         mContentView = mInflater.inflate(layoutId, nullfalse);  
  39.         if (mInflater == null || mContentView == null) {  
  40.             throw new RuntimeException(  
  41.                     "ViewFinder init failed, mInflater == null || mContentView == null.");  
  42.         }  
  43.     }  
  44.   
  45.     /** 
  46.      * @return 
  47.      */  
  48.     public static View getContentView() {  
  49.         return mContentView;  
  50.     }  
  51.   
  52.     /** 
  53.      * @param viewId 
  54.      * @return 
  55.      */  
  56.     @SuppressWarnings("unchecked")  
  57.     public static <T extends View> T findViewById(int viewId) {  
  58.         // 先从view map中查找,如果有的缓存的话直接使用,否则再从mContentView中找  
  59.         View tagetView = mViewMap.get(viewId);  
  60.         if (tagetView == null) {  
  61.             tagetView = mContentView.findViewById(viewId);  
  62.             mViewMap.put(viewId, tagetView);  
  63.         }  
  64.         return tagetView == null ? null : (T) mContentView.findViewById(viewId);  
  65.     }  
  66. }  

         代码都在Github上了,请猛击这里

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值