Android中适用于ListView、GridView等组件的通用Adapter (转)
2014-12-24 14:17
525 查看
今天随便逛逛CSDN,看到主页上推荐了一篇文章Android 快速开发系列 打造万能的ListView GridView 适配器,刚好这两天写项目自己也封装了类似的CommonAdapter,以前也在github上看到过这样的库,于是自己也把自己的代码再次整理出来与大家分享,也希望能够在CSDN这个平台上学到更多的东西,下面就一起来看看吧。
平时我们在项目中使用到ListView和GridView组件都是都会用到Adapter,比较多的情况是继承自BaseAdapter,然后实现getCount、getView等方法,再使用ViewHolder来提高一下效率.我们看下面一个简单的例子 :
fragment_main.xml :
listview_item_layout.xml :
[html]
view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/my_imageview"
android:layout_width="64dp"
android:layout_height="64dp"
android:contentDescription="@string/app_name" />
<TextView
android:id="@+id/my_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:textSize="18sp" />
</LinearLayout>
[java]
view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
public class NormalAdapter extends BaseAdapter { Context mContext; LayoutInflater mInflater; List<ListViewItem> mDataList; /** * @param context * @param data */ public NormalAdapter(Context context, List<ListViewItem> data) { mContext = context; mInflater = LayoutInflater.from(context); mDataList = data; } @Override public int getCount() { return mDataList.size(); } @Override public ListViewItem getItem(int position) { return mDataList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.listview_item_layout, null, false); viewHolder = new ViewHolder(); viewHolder.mImageView = (ImageView) convertView.findViewById(R.id.my_imageview); viewHolder.mTextView = (TextView) convertView.findViewById(R.id.my_textview); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.mImageView.setImageResource(getItem(position).mDrawableId); viewHolder.mTextView.setText(getItem(position).mText); return convertView; } /** * ViewHolder * * @author mrsimple */ static class ViewHolder { ImageView mImageView; TextView mTextView; } }
然而写过多遍以后我们发现我们总是重复地在写这些getCount、getItem、getView方法以及ViewHolder,导致了很多重复工作,而且及其无聊,于是我把这些重复工作抽象起来(以前也有在github上看到这样的通用Adapter实现),整理一下也便于自己使用,也是自己学习的一个过程。下面我们看看使用CommonAdapter后我们做与上面同样的工作需要怎么写。
[java]
view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
CommonAdapter<ListViewItem> listAdapter = new CommonAdapter<ListViewItem>(getActivity(), R.layout.listview_item_layout, mockListViewItems()) { @Override protected void fillItemData(CommonViewHolder viewHolder, ListViewItem item) { // 设置图片 viewHolder.setImageForView(R.id.my_imageview, item.mDrawableId); // 设置text viewHolder.setTextForTextView(R.id.my_textview, item.mText); } }
其中mockListViewImtes是准备了一些数据, 代码如下 :
[java]
view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
/**
* 模拟一些数据
*
* @return
*/
private List<ListViewItem> mockListViewItems() {
List<ListViewItem> dataItems = new ArrayList<ListViewItem>();
dataItems.add(new ListViewItem(R.drawable.girl_96, "girl_96.png"));
dataItems.add(new ListViewItem(R.drawable.fire_96, "fire_96.png"));
dataItems.add(new ListViewItem(R.drawable.grimace_96, "grimace_96.png"));
dataItems.add(new ListViewItem(R.drawable.laugh_96, "laugh_96.png"));
return dataItems;
}
可以看到,我们的代码量减少了很多,如果一个项目中有好几个ListView、GridView等组件,我们就不需要重复做那么多无聊的工作了。我们看看效果图 :
![](http://img.blog.csdn.net/20141224141902182?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbXlwYW5sb25n/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
CommonAdapter实现
[java]
view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
/**
*
* created by Mr.Simple, Aug 28, 201412:26:52 PM.
* Copyright (c) 2014, hehonghui@umeng.com All Rights Reserved.
*
* #####################################################
* # #
* # _oo0oo_ #
* # o8888888o #
* # 88" . "88 #
* # (| -_- |) #
* # 0\ = /0 #
* # ___/`---'\___ #
* # .' \\| |# '. #
* # / \\||| : |||# \ #
* # / _||||| -:- |||||- \ #
* # | | \\\ - #/ | | #
* # | \_| ''\---/'' |_/ | #
* # \ .-\__ '-' ___/-. / #
* # ___'. .' /--.--\ `. .'___ #
* # ."" '< `.___\_<|>_/___.' >' "". #
* # | | : `- \`.;`\ _ /`;.`/ - ` : | | #
* # \ \ `_. \_ __\ /__ _/ .-` / / #
* # =====`-.____`.___ \_____/___.-`___.-'===== #
* # `=---=' #
* # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
* # #
* # 佛祖保佑 永无BUG #
* # #
* #####################################################
*/
package com.uit.commons;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.List;
/**
* 这是一个通用、抽象的适配器类,覆写了BaseAdapter的getCount, getItem, getItemId,
* getView方法,在getView方法中通过
* 通用的CommonViewHolder来对convertView的进行处理,并且缓存convertView中的其他View元素
* ,降低了ListView、GridView 等组件的Adapter和ViewHolder的代码量.
* 用户只需要在fillItemData函数中将第position位置里的数据填充到listview或者gridview的第position的view中即可
* ,具体使用实例参考文档.
*
* @author mrsimple
* @param <T> 数据源的类型
*/
public abstract class CommonAdapter<T> extends BaseAdapter {
/**
* Context
*/
Context mContext;
/**
* 要展示的数据列表
*/
List<T> mData;
/**
* 每一项的布局id,例如R.layout.my_listview_item.
*/
private int mItemLayoutId = -1;
/**
* @param context Context
* @param itemLayoutResId
* 每一项(适用于listview、gridview等AbsListView子类)的布局资源id,例如R.layout.
* my_listview_item.
* @param dataSource 数据源
*/
public CommonAdapter(Context context, int itemLayoutResId, List<T> dataSource) {
checkParams(context, itemLayoutResId, dataSource);
mContext = context;
mItemLayoutId = itemLayoutResId;
mData = dataSource;
}
/**
* 检查参数的有效性
*
* @param context
* @param itemLayoutResId
* @param dataSource
*/
private void checkParams(Context context, int itemLayoutResId, List<T> dataSource) {
if (context == null || itemLayoutResId < 0 || dataSource == null) {
throw new RuntimeException(
"context == null || itemLayoutResId < 0 || dataSource == null, please check your params");
}
}
/**
* 返回数据的总数
*/
@Override
public int getCount() {
return mData.size();
}
/**
* 返回position位置的数据
*/
@Override
public T getItem(int position) {
return mData.get(position);
}
/**
* item id, 返回position
*/
@Override
public long getItemId(int position) {
return position;
}
/**
* 返回position位置的view, 即listview、gridview的第postion个view
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 获取ViewHolder
CommonViewHolder viewHolder = CommonViewHolder.getViewHolder(mContext, convertView,
mItemLayoutId);
// 填充数据
fillItemData(viewHolder, getItem(position));
// 返回convertview
return viewHolder.getConvertView();
}
/**
* 用户必须覆写该方法来讲数据填充到视图中
*
* @param viewHolder 通用的ViewHolder, 里面会装载listview,
* gridview等组件的每一项的视图,并且缓存其子view
* @param item 数据源的第position项数据
*/
protected abstract void fillItemData(CommonViewHolder viewHolder, T item);
}
CommonViewHolder实现
[java]
view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
/**
*
* created by Mr.Simple, Aug 28, 201412:32:45 PM.
* Copyright (c) 2014, hehonghui@umeng.com All Rights Reserved.
*
* #####################################################
* # #
* # _oo0oo_ #
* # o8888888o #
* # 88" . "88 #
* # (| -_- |) #
* # 0\ = /0 #
* # ___/`---'\___ #
* # .' \\| |# '. #
* # / \\||| : |||# \ #
* # / _||||| -:- |||||- \ #
* # | | \\\ - #/ | | #
* # | \_| ''\---/'' |_/ | #
* # \ .-\__ '-' ___/-. / #
* # ___'. .' /--.--\ `. .'___ #
* # ."" '< `.___\_<|>_/___.' >' "". #
* # | | : `- \`.;`\ _ /`;.`/ - ` : | | #
* # \ \ `_. \_ __\ /__ _/ .-` / / #
* # =====`-.____`.___ \_____/___.-`___.-'===== #
* # `=---=' #
* # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
* # #
* # 佛祖保佑 永无BUG #
* # #
* #####################################################
*/
package com.uit.commons;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import com.uit.commons.utils.ViewFinder;
/**
* 这是一个通用的ViewHolder, 将会装载AbsListView子类的item View, 并且将item
* view中的子视图进行缓存和索引,使得用户能够方便的获取这些子view, 减少了代码重复。
*
* @author mrsimple
*/
public class CommonViewHolder {
/**
* 构造函数
*
* @param context Context
* @param layoutId ListView、GridView或者其他AbsListVew子类的 Item View的资源布局id
*/
protected CommonViewHolder(Context context, int layoutId) {
// 初始化布局, 装载ContentView
ViewFinder.initContentView(context, layoutId);
// 将ViewHolder存储在ContentView的tag中
ViewFinder.getContentView().setTag(this);
}
/**
* 获取CommonViewHolder,当convertView为空的时候从布局xml装载item view,
* 并且将该CommonViewHolder设置为convertView的tag, 便于复用convertView.
*
* @param context Context
* @param convertView Item view
* @param layoutId 布局资源id, 例如R.layout.my_listview_item.
* @return 通用的CommonViewHolder实例
*/
public static CommonViewHolder getViewHolder(Context context, View convertView, int layoutId) {
if (convertView == null) {
return new CommonViewHolder(context, layoutId);
}
return (CommonViewHolder) convertView.getTag();
}
/**
* @return 当前项的convertView, 在构造函数中装载
*/
public View getConvertView() {
return ViewFinder.getContentView();
}
/**
* 为id为textViewId的TextView设置文本内容
*
* @param textViewId 视图id
* @param text 要设置的文本内容
*/
public void setTextForTextView(int textViewId, CharSequence text) {
TextView textView = ViewFinder.findViewById(textViewId);
if (textView != null) {
textView.setText(text);
}
}
/**
* 为ImageView设置图片
*
* @param imageViewId ImageView的id, 例如R.id.my_imageview
* @param drawableId Drawable图片的id, 例如R.drawable.my_photo
*/
public void setImageForView(int imageViewId, int drawableId) {
ImageView imageView = ViewFinder.findViewById(imageViewId);
if (imageView != null) {
imageView.setImageResource(drawableId);
}
}
/**
* 为ImageView设置图片
*
* @param imageViewId ImageView的id, 例如R.id.my_imageview
* @param bmp Bitmap图片
*/
public void setImageForView(int imageViewId, Bitmap bmp) {
ImageView imageView = ViewFinder.findViewById(imageViewId);
if (imageView != null) {
imageView.setImageBitmap(bmp);
}
}
/**
* 为CheckBox设置是否选中
*
* @param checkViewId CheckBox的id
* @param isCheck 是否选中
*/
public void setCheckForCheckBox(int checkViewId, boolean isCheck) {
CheckBox checkBox = ViewFinder.findViewById(checkViewId);
if (checkBox != null) {
checkBox.setChecked(isCheck);
}
}
}
ViewFinder辅助类
[java]
view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
![](https://code.csdn.net/assets/ico_fork.svg)
/** * view finder, 方便查找View。用户需要在使用时调用initContentView, * 将Context和布局id传进来,然后使用findViewById来获取需要的view * ,findViewById为泛型方法,返回的view则直接是你接收的类型,而不需要进行强制类型转换.比如, * 以前我们在Activity中找一个TextView一般是这样 : * TextView textView = (TextView)findViewById(viewId); * 如果页面中的控件比较多,就会有很多的类型转换,而使用ViewFinder则免去了类型转换, * 示例如下 : * TextView textView = ViewFinder.findViewById(viewId); * * @author mrsimple */ public final class ViewFinder { /** * LayoutInflater */ static LayoutInflater mInflater; /** * 每项的View的sub view Map */ private static SparseArray<View> mViewMap = new SparseArray<View>(); /** * Content View */ static View mContentView; /** * 初始化ViewFinder, 实际上是获取到该页面的ContentView. * * @param context * @param layoutId */ public static void initContentView(Context context, int layoutId) { mInflater = LayoutInflater.from(context); mContentView = mInflater.inflate(layoutId, null, false); if (mInflater == null || mContentView == null) { throw new RuntimeException( "ViewFinder init failed, mInflater == null || mContentView == null."); } } /** * @return */ public static View getContentView() { return mContentView; } /** * @param viewId * @return */ @SuppressWarnings("unchecked") public static <T extends View> T findViewById(int viewId) { // 先从view map中查找,如果有的缓存的话直接使用,否则再从mContentView中找 View tagetView = mViewMap.get(viewId); if (tagetView == null) { tagetView = mContentView.findViewById(viewId); mViewMap.put(viewId, tagetView); } return tagetView == null ? null : (T) mContentView.findViewById(viewId); } }
代码都在Github上了,请猛击这里。
平时我们在项目中使用到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 plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<ImageView
android:id="@+id/my_imageview"
android:layout_width="64dp"
android:layout_height="64dp"
android:contentDescription="@string/app_name" />
<TextView
android:id="@+id/my_textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:textSize="18sp" />
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <ImageView android:id="@+id/my_imageview" android:layout_width="64dp" android:layout_height="64dp" android:contentDescription="@string/app_name" /> <TextView android:id="@+id/my_textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:textSize="18sp" /> </LinearLayout>
曾经我们要写下的Adapter代码
[java]view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
public class NormalAdapter extends BaseAdapter { Context mContext; LayoutInflater mInflater; List<ListViewItem> mDataList; /** * @param context * @param data */ public NormalAdapter(Context context, List<ListViewItem> data) { mContext = context; mInflater = LayoutInflater.from(context); mDataList = data; } @Override public int getCount() { return mDataList.size(); } @Override public ListViewItem getItem(int position) { return mDataList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.listview_item_layout, null, false); viewHolder = new ViewHolder(); viewHolder.mImageView = (ImageView) convertView.findViewById(R.id.my_imageview); viewHolder.mTextView = (TextView) convertView.findViewById(R.id.my_textview); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.mImageView.setImageResource(getItem(position).mDrawableId); viewHolder.mTextView.setText(getItem(position).mText); return convertView; } /** * ViewHolder * * @author mrsimple */ static class ViewHolder { ImageView mImageView; TextView mTextView; } }
public class NormalAdapter extends BaseAdapter { Context mContext; LayoutInflater mInflater; List<ListViewItem> mDataList; /** * @param context * @param data */ public NormalAdapter(Context context, List<ListViewItem> data) { mContext = context; mInflater = LayoutInflater.from(context); mDataList = data; } @Override public int getCount() { return mDataList.size(); } @Override public ListViewItem getItem(int position) { return mDataList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.listview_item_layout, null, false); viewHolder = new ViewHolder(); viewHolder.mImageView = (ImageView) convertView.findViewById(R.id.my_imageview); viewHolder.mTextView = (TextView) convertView.findViewById(R.id.my_textview); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } viewHolder.mImageView.setImageResource(getItem(position).mDrawableId); viewHolder.mTextView.setText(getItem(position).mText); return convertView; } /** * ViewHolder * * @author mrsimple */ static class ViewHolder { ImageView mImageView; TextView mTextView; } }
然而写过多遍以后我们发现我们总是重复地在写这些getCount、getItem、getView方法以及ViewHolder,导致了很多重复工作,而且及其无聊,于是我把这些重复工作抽象起来(以前也有在github上看到这样的通用Adapter实现),整理一下也便于自己使用,也是自己学习的一个过程。下面我们看看使用CommonAdapter后我们做与上面同样的工作需要怎么写。
使用CommonAdapter后要写的代码
[java]view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
CommonAdapter<ListViewItem> listAdapter = new CommonAdapter<ListViewItem>(getActivity(), R.layout.listview_item_layout, mockListViewItems()) { @Override protected void fillItemData(CommonViewHolder viewHolder, ListViewItem item) { // 设置图片 viewHolder.setImageForView(R.id.my_imageview, item.mDrawableId); // 设置text viewHolder.setTextForTextView(R.id.my_textview, item.mText); } }
CommonAdapter<ListViewItem> listAdapter = new CommonAdapter<ListViewItem>(getActivity(), R.layout.listview_item_layout, mockListViewItems()) { @Override protected void fillItemData(CommonViewHolder viewHolder, ListViewItem item) { // 设置图片 viewHolder.setImageForView(R.id.my_imageview, item.mDrawableId); // 设置text viewHolder.setTextForTextView(R.id.my_textview, item.mText); } }
其中mockListViewImtes是准备了一些数据, 代码如下 :
[java]
view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
/**
* 模拟一些数据
*
* @return
*/
private List<ListViewItem> mockListViewItems() {
List<ListViewItem> dataItems = new ArrayList<ListViewItem>();
dataItems.add(new ListViewItem(R.drawable.girl_96, "girl_96.png"));
dataItems.add(new ListViewItem(R.drawable.fire_96, "fire_96.png"));
dataItems.add(new ListViewItem(R.drawable.grimace_96, "grimace_96.png"));
dataItems.add(new ListViewItem(R.drawable.laugh_96, "laugh_96.png"));
return dataItems;
}
/** * 模拟一些数据 * * @return */ private List<ListViewItem> mockListViewItems() { List<ListViewItem> dataItems = new ArrayList<ListViewItem>(); dataItems.add(new ListViewItem(R.drawable.girl_96, "girl_96.png")); dataItems.add(new ListViewItem(R.drawable.fire_96, "fire_96.png")); dataItems.add(new ListViewItem(R.drawable.grimace_96, "grimace_96.png")); dataItems.add(new ListViewItem(R.drawable.laugh_96, "laugh_96.png")); return dataItems; }
可以看到,我们的代码量减少了很多,如果一个项目中有好几个ListView、GridView等组件,我们就不需要重复做那么多无聊的工作了。我们看看效果图 :
CommonAdapter实现
[java]
view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
/**
*
* created by Mr.Simple, Aug 28, 201412:26:52 PM.
* Copyright (c) 2014, hehonghui@umeng.com All Rights Reserved.
*
* #####################################################
* # #
* # _oo0oo_ #
* # o8888888o #
* # 88" . "88 #
* # (| -_- |) #
* # 0\ = /0 #
* # ___/`---'\___ #
* # .' \\| |# '. #
* # / \\||| : |||# \ #
* # / _||||| -:- |||||- \ #
* # | | \\\ - #/ | | #
* # | \_| ''\---/'' |_/ | #
* # \ .-\__ '-' ___/-. / #
* # ___'. .' /--.--\ `. .'___ #
* # ."" '< `.___\_<|>_/___.' >' "". #
* # | | : `- \`.;`\ _ /`;.`/ - ` : | | #
* # \ \ `_. \_ __\ /__ _/ .-` / / #
* # =====`-.____`.___ \_____/___.-`___.-'===== #
* # `=---=' #
* # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
* # #
* # 佛祖保佑 永无BUG #
* # #
* #####################################################
*/
package com.uit.commons;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.List;
/**
* 这是一个通用、抽象的适配器类,覆写了BaseAdapter的getCount, getItem, getItemId,
* getView方法,在getView方法中通过
* 通用的CommonViewHolder来对convertView的进行处理,并且缓存convertView中的其他View元素
* ,降低了ListView、GridView 等组件的Adapter和ViewHolder的代码量.
* 用户只需要在fillItemData函数中将第position位置里的数据填充到listview或者gridview的第position的view中即可
* ,具体使用实例参考文档.
*
* @author mrsimple
* @param <T> 数据源的类型
*/
public abstract class CommonAdapter<T> extends BaseAdapter {
/**
* Context
*/
Context mContext;
/**
* 要展示的数据列表
*/
List<T> mData;
/**
* 每一项的布局id,例如R.layout.my_listview_item.
*/
private int mItemLayoutId = -1;
/**
* @param context Context
* @param itemLayoutResId
* 每一项(适用于listview、gridview等AbsListView子类)的布局资源id,例如R.layout.
* my_listview_item.
* @param dataSource 数据源
*/
public CommonAdapter(Context context, int itemLayoutResId, List<T> dataSource) {
checkParams(context, itemLayoutResId, dataSource);
mContext = context;
mItemLayoutId = itemLayoutResId;
mData = dataSource;
}
/**
* 检查参数的有效性
*
* @param context
* @param itemLayoutResId
* @param dataSource
*/
private void checkParams(Context context, int itemLayoutResId, List<T> dataSource) {
if (context == null || itemLayoutResId < 0 || dataSource == null) {
throw new RuntimeException(
"context == null || itemLayoutResId < 0 || dataSource == null, please check your params");
}
}
/**
* 返回数据的总数
*/
@Override
public int getCount() {
return mData.size();
}
/**
* 返回position位置的数据
*/
@Override
public T getItem(int position) {
return mData.get(position);
}
/**
* item id, 返回position
*/
@Override
public long getItemId(int position) {
return position;
}
/**
* 返回position位置的view, 即listview、gridview的第postion个view
*/
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 获取ViewHolder
CommonViewHolder viewHolder = CommonViewHolder.getViewHolder(mContext, convertView,
mItemLayoutId);
// 填充数据
fillItemData(viewHolder, getItem(position));
// 返回convertview
return viewHolder.getConvertView();
}
/**
* 用户必须覆写该方法来讲数据填充到视图中
*
* @param viewHolder 通用的ViewHolder, 里面会装载listview,
* gridview等组件的每一项的视图,并且缓存其子view
* @param item 数据源的第position项数据
*/
protected abstract void fillItemData(CommonViewHolder viewHolder, T item);
}
/** * * created by Mr.Simple, Aug 28, 201412:26:52 PM. * Copyright (c) 2014, hehonghui@umeng.com All Rights Reserved. * * ##################################################### * # # * # _oo0oo_ # * # o8888888o # * # 88" . "88 # * # (| -_- |) # * # 0\ = /0 # * # ___/`---'\___ # * # .' \\| |# '. # * # / \\||| : |||# \ # * # / _||||| -:- |||||- \ # * # | | \\\ - #/ | | # * # | \_| ''\---/'' |_/ | # * # \ .-\__ '-' ___/-. / # * # ___'. .' /--.--\ `. .'___ # * # ."" '< `.___\_<|>_/___.' >' "". # * # | | : `- \`.;`\ _ /`;.`/ - ` : | | # * # \ \ `_. \_ __\ /__ _/ .-` / / # * # =====`-.____`.___ \_____/___.-`___.-'===== # * # `=---=' # * # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * # # * # 佛祖保佑 永无BUG # * # # * ##################################################### */ package com.uit.commons; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import java.util.List; /** * 这是一个通用、抽象的适配器类,覆写了BaseAdapter的getCount, getItem, getItemId, * getView方法,在getView方法中通过 * 通用的CommonViewHolder来对convertView的进行处理,并且缓存convertView中的其他View元素 * ,降低了ListView、GridView 等组件的Adapter和ViewHolder的代码量. * 用户只需要在fillItemData函数中将第position位置里的数据填充到listview或者gridview的第position的view中即可 * ,具体使用实例参考文档. * * @author mrsimple * @param <T> 数据源的类型 */ public abstract class CommonAdapter<T> extends BaseAdapter { /** * Context */ Context mContext; /** * 要展示的数据列表 */ List<T> mData; /** * 每一项的布局id,例如R.layout.my_listview_item. */ private int mItemLayoutId = -1; /** * @param context Context * @param itemLayoutResId * 每一项(适用于listview、gridview等AbsListView子类)的布局资源id,例如R.layout. * my_listview_item. * @param dataSource 数据源 */ public CommonAdapter(Context context, int itemLayoutResId, List<T> dataSource) { checkParams(context, itemLayoutResId, dataSource); mContext = context; mItemLayoutId = itemLayoutResId; mData = dataSource; } /** * 检查参数的有效性 * * @param context * @param itemLayoutResId * @param dataSource */ private void checkParams(Context context, int itemLayoutResId, List<T> dataSource) { if (context == null || itemLayoutResId < 0 || dataSource == null) { throw new RuntimeException( "context == null || itemLayoutResId < 0 || dataSource == null, please check your params"); } } /** * 返回数据的总数 */ @Override public int getCount() { return mData.size(); } /** * 返回position位置的数据 */ @Override public T getItem(int position) { return mData.get(position); } /** * item id, 返回position */ @Override public long getItemId(int position) { return position; } /** * 返回position位置的view, 即listview、gridview的第postion个view */ @Override public View getView(int position, View convertView, ViewGroup parent) { // 获取ViewHolder CommonViewHolder viewHolder = CommonViewHolder.getViewHolder(mContext, convertView, mItemLayoutId); // 填充数据 fillItemData(viewHolder, getItem(position)); // 返回convertview return viewHolder.getConvertView(); } /** * 用户必须覆写该方法来讲数据填充到视图中 * * @param viewHolder 通用的ViewHolder, 里面会装载listview, * gridview等组件的每一项的视图,并且缓存其子view * @param item 数据源的第position项数据 */ protected abstract void fillItemData(CommonViewHolder viewHolder, T item); }
CommonViewHolder实现
[java]
view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
/**
*
* created by Mr.Simple, Aug 28, 201412:32:45 PM.
* Copyright (c) 2014, hehonghui@umeng.com All Rights Reserved.
*
* #####################################################
* # #
* # _oo0oo_ #
* # o8888888o #
* # 88" . "88 #
* # (| -_- |) #
* # 0\ = /0 #
* # ___/`---'\___ #
* # .' \\| |# '. #
* # / \\||| : |||# \ #
* # / _||||| -:- |||||- \ #
* # | | \\\ - #/ | | #
* # | \_| ''\---/'' |_/ | #
* # \ .-\__ '-' ___/-. / #
* # ___'. .' /--.--\ `. .'___ #
* # ."" '< `.___\_<|>_/___.' >' "". #
* # | | : `- \`.;`\ _ /`;.`/ - ` : | | #
* # \ \ `_. \_ __\ /__ _/ .-` / / #
* # =====`-.____`.___ \_____/___.-`___.-'===== #
* # `=---=' #
* # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #
* # #
* # 佛祖保佑 永无BUG #
* # #
* #####################################################
*/
package com.uit.commons;
import android.content.Context;
import android.graphics.Bitmap;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import com.uit.commons.utils.ViewFinder;
/**
* 这是一个通用的ViewHolder, 将会装载AbsListView子类的item View, 并且将item
* view中的子视图进行缓存和索引,使得用户能够方便的获取这些子view, 减少了代码重复。
*
* @author mrsimple
*/
public class CommonViewHolder {
/**
* 构造函数
*
* @param context Context
* @param layoutId ListView、GridView或者其他AbsListVew子类的 Item View的资源布局id
*/
protected CommonViewHolder(Context context, int layoutId) {
// 初始化布局, 装载ContentView
ViewFinder.initContentView(context, layoutId);
// 将ViewHolder存储在ContentView的tag中
ViewFinder.getContentView().setTag(this);
}
/**
* 获取CommonViewHolder,当convertView为空的时候从布局xml装载item view,
* 并且将该CommonViewHolder设置为convertView的tag, 便于复用convertView.
*
* @param context Context
* @param convertView Item view
* @param layoutId 布局资源id, 例如R.layout.my_listview_item.
* @return 通用的CommonViewHolder实例
*/
public static CommonViewHolder getViewHolder(Context context, View convertView, int layoutId) {
if (convertView == null) {
return new CommonViewHolder(context, layoutId);
}
return (CommonViewHolder) convertView.getTag();
}
/**
* @return 当前项的convertView, 在构造函数中装载
*/
public View getConvertView() {
return ViewFinder.getContentView();
}
/**
* 为id为textViewId的TextView设置文本内容
*
* @param textViewId 视图id
* @param text 要设置的文本内容
*/
public void setTextForTextView(int textViewId, CharSequence text) {
TextView textView = ViewFinder.findViewById(textViewId);
if (textView != null) {
textView.setText(text);
}
}
/**
* 为ImageView设置图片
*
* @param imageViewId ImageView的id, 例如R.id.my_imageview
* @param drawableId Drawable图片的id, 例如R.drawable.my_photo
*/
public void setImageForView(int imageViewId, int drawableId) {
ImageView imageView = ViewFinder.findViewById(imageViewId);
if (imageView != null) {
imageView.setImageResource(drawableId);
}
}
/**
* 为ImageView设置图片
*
* @param imageViewId ImageView的id, 例如R.id.my_imageview
* @param bmp Bitmap图片
*/
public void setImageForView(int imageViewId, Bitmap bmp) {
ImageView imageView = ViewFinder.findViewById(imageViewId);
if (imageView != null) {
imageView.setImageBitmap(bmp);
}
}
/**
* 为CheckBox设置是否选中
*
* @param checkViewId CheckBox的id
* @param isCheck 是否选中
*/
public void setCheckForCheckBox(int checkViewId, boolean isCheck) {
CheckBox checkBox = ViewFinder.findViewById(checkViewId);
if (checkBox != null) {
checkBox.setChecked(isCheck);
}
}
}
/** * * created by Mr.Simple, Aug 28, 201412:32:45 PM. * Copyright (c) 2014, hehonghui@umeng.com All Rights Reserved. * * ##################################################### * # # * # _oo0oo_ # * # o8888888o # * # 88" . "88 # * # (| -_- |) # * # 0\ = /0 # * # ___/`---'\___ # * # .' \\| |# '. # * # / \\||| : |||# \ # * # / _||||| -:- |||||- \ # * # | | \\\ - #/ | | # * # | \_| ''\---/'' |_/ | # * # \ .-\__ '-' ___/-. / # * # ___'. .' /--.--\ `. .'___ # * # ."" '< `.___\_<|>_/___.' >' "". # * # | | : `- \`.;`\ _ /`;.`/ - ` : | | # * # \ \ `_. \_ __\ /__ _/ .-` / / # * # =====`-.____`.___ \_____/___.-`___.-'===== # * # `=---=' # * # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # * # # * # 佛祖保佑 永无BUG # * # # * ##################################################### */ package com.uit.commons; import android.content.Context; import android.graphics.Bitmap; import android.view.View; import android.widget.CheckBox; import android.widget.ImageView; import android.widget.TextView; import com.uit.commons.utils.ViewFinder; /** * 这是一个通用的ViewHolder, 将会装载AbsListView子类的item View, 并且将item * view中的子视图进行缓存和索引,使得用户能够方便的获取这些子view, 减少了代码重复。 * * @author mrsimple */ public class CommonViewHolder { /** * 构造函数 * * @param context Context * @param layoutId ListView、GridView或者其他AbsListVew子类的 Item View的资源布局id */ protected CommonViewHolder(Context context, int layoutId) { // 初始化布局, 装载ContentView ViewFinder.initContentView(context, layoutId); // 将ViewHolder存储在ContentView的tag中 ViewFinder.getContentView().setTag(this); } /** * 获取CommonViewHolder,当convertView为空的时候从布局xml装载item view, * 并且将该CommonViewHolder设置为convertView的tag, 便于复用convertView. * * @param context Context * @param convertView Item view * @param layoutId 布局资源id, 例如R.layout.my_listview_item. * @return 通用的CommonViewHolder实例 */ public static CommonViewHolder getViewHolder(Context context, View convertView, int layoutId) { if (convertView == null) { return new CommonViewHolder(context, layoutId); } return (CommonViewHolder) convertView.getTag(); } /** * @return 当前项的convertView, 在构造函数中装载 */ public View getConvertView() { return ViewFinder.getContentView(); } /** * 为id为textViewId的TextView设置文本内容 * * @param textViewId 视图id * @param text 要设置的文本内容 */ public void setTextForTextView(int textViewId, CharSequence text) { TextView textView = ViewFinder.findViewById(textViewId); if (textView != null) { textView.setText(text); } } /** * 为ImageView设置图片 * * @param imageViewId ImageView的id, 例如R.id.my_imageview * @param drawableId Drawable图片的id, 例如R.drawable.my_photo */ public void setImageForView(int imageViewId, int drawableId) { ImageView imageView = ViewFinder.findViewById(imageViewId); if (imageView != null) { imageView.setImageResource(drawableId); } } /** * 为ImageView设置图片 * * @param imageViewId ImageView的id, 例如R.id.my_imageview * @param bmp Bitmap图片 */ public void setImageForView(int imageViewId, Bitmap bmp) { ImageView imageView = ViewFinder.findViewById(imageViewId); if (imageView != null) { imageView.setImageBitmap(bmp); } } /** * 为CheckBox设置是否选中 * * @param checkViewId CheckBox的id * @param isCheck 是否选中 */ public void setCheckForCheckBox(int checkViewId, boolean isCheck) { CheckBox checkBox = ViewFinder.findViewById(checkViewId); if (checkBox != null) { checkBox.setChecked(isCheck); } } }
ViewFinder辅助类
[java]
view plaincopyprint?
![](https://code.csdn.net/assets/CODE_ico.png)
/** * view finder, 方便查找View。用户需要在使用时调用initContentView, * 将Context和布局id传进来,然后使用findViewById来获取需要的view * ,findViewById为泛型方法,返回的view则直接是你接收的类型,而不需要进行强制类型转换.比如, * 以前我们在Activity中找一个TextView一般是这样 : * TextView textView = (TextView)findViewById(viewId); * 如果页面中的控件比较多,就会有很多的类型转换,而使用ViewFinder则免去了类型转换, * 示例如下 : * TextView textView = ViewFinder.findViewById(viewId); * * @author mrsimple */ public final class ViewFinder { /** * LayoutInflater */ static LayoutInflater mInflater; /** * 每项的View的sub view Map */ private static SparseArray<View> mViewMap = new SparseArray<View>(); /** * Content View */ static View mContentView; /** * 初始化ViewFinder, 实际上是获取到该页面的ContentView. * * @param context * @param layoutId */ public static void initContentView(Context context, int layoutId) { mInflater = LayoutInflater.from(context); mContentView = mInflater.inflate(layoutId, null, false); if (mInflater == null || mContentView == null) { throw new RuntimeException( "ViewFinder init failed, mInflater == null || mContentView == null."); } } /** * @return */ public static View getContentView() { return mContentView; } /** * @param viewId * @return */ @SuppressWarnings("unchecked") public static <T extends View> T findViewById(int viewId) { // 先从view map中查找,如果有的缓存的话直接使用,否则再从mContentView中找 View tagetView = mViewMap.get(viewId); if (tagetView == null) { tagetView = mContentView.findViewById(viewId); mViewMap.put(viewId, tagetView); } return tagetView == null ? null : (T) mContentView.findViewById(viewId); } }
/** * view finder, 方便查找View。用户需要在使用时调用initContentView, * 将Context和布局id传进来,然后使用findViewById来获取需要的view * ,findViewById为泛型方法,返回的view则直接是你接收的类型,而不需要进行强制类型转换.比如, * 以前我们在Activity中找一个TextView一般是这样 : * TextView textView = (TextView)findViewById(viewId); * 如果页面中的控件比较多,就会有很多的类型转换,而使用ViewFinder则免去了类型转换, * 示例如下 : * TextView textView = ViewFinder.findViewById(viewId); * * @author mrsimple */ public final class ViewFinder { /** * LayoutInflater */ static LayoutInflater mInflater; /** * 每项的View的sub view Map */ private static SparseArray<View> mViewMap = new SparseArray<View>(); /** * Content View */ static View mContentView; /** * 初始化ViewFinder, 实际上是获取到该页面的ContentView. * * @param context * @param layoutId */ public static void initContentView(Context context, int layoutId) { mInflater = LayoutInflater.from(context); mContentView = mInflater.inflate(layoutId, null, false); if (mInflater == null || mContentView == null) { throw new RuntimeException( "ViewFinder init failed, mInflater == null || mContentView == null."); } } /** * @return */ public static View getContentView() { return mContentView; } /** * @param viewId * @return */ @SuppressWarnings("unchecked") public static <T extends View> T findViewById(int viewId) { // 先从view map中查找,如果有的缓存的话直接使用,否则再从mContentView中找 View tagetView = mViewMap.get(viewId); if (tagetView == null) { tagetView = mContentView.findViewById(viewId); mViewMap.put(viewId, tagetView); } return tagetView == null ? null : (T) mContentView.findViewById(viewId); } }
代码都在Github上了,请猛击这里。
相关文章推荐
- Android中适用于ListView、GridView等组件的通用Adapter
- Android中适用于ListView、GridView等组件的通用Adapter
- Android中适用于ListView、GridView等组件的通用Adapter
- Android中适用于ListView、GridView等组件的通用Adapter
- 打造通用的Android下拉刷新组件(适用于ListView、GridView等各类View)
- 打造通用的Android下拉刷新组件(适用于ListView、GridView等各类View)
- 打造通用的Android下拉刷新组件(适用于ListView、GridView等各类View)
- 【转android】(ListView、GridView等)通用的下拉刷新、上拉自动加载的组件
- Android打造(ListView、GridView等)通用的下拉刷新、上拉自动加载的组件
- Android打造(ListView、GridView等)通用的下拉刷新、上拉自动加载的组件
- Android打造(ListView、GridView等)通用的下拉刷新、上拉自动加载的组件
- Android打造(ListView、GridView等)通用的下拉刷新、上拉自动加载的组件
- Android打造(ListView、GridView等)通用的下拉刷新、上拉自动加载的组件
- 打造通用Adapter(适用于ListView,GridView)
- android 学习笔记:自定义通用ListView/GridView,实现ListAdapter 类
- Android中万能的BaseAdapter(Spinner,ListView,GridView)的使用!
- Android高手进阶教程(十六)之---Android中万能的BaseAdapter(Spinner,ListView,GridView)的使用!
- android Adapter综合使用(ArrayAdapter、SimpleAdapter、BaseAdapter在ListView和GridView中的使用)
- 【Android】以SimpleAdapter做适配器的ListView和GridView
- 【Android】以SimpleAdapter做适配器的ListView和GridView