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 :
<?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代码
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后要写的代码
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是准备了一些数据, 代码例如以下 :
/**
* 模拟一些数据
*
* @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实现
/**
*
* 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实现
/**
*
* 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辅助类
/**
* 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
原文网址:http://sunbofu.blog.51cto.com/6431507/1280441 Android中的listview目测是一个使用频率很高的组件,所以今天来总结一下listview ...
- Android中使用ListView绘制自定义表格(2)
上回再写了<Android中使用ListView绘制自定义表格>后,很多人留言代码不全和没有数据样例.但因为项目原因,没法把源码全部贴上来.近两天,抽空简化了一下,做了一个例子. 效果图如 ...
- Android中实现ListView圆角效果[转]
本文演示如何Android中实现ListView圆角效果. 无论是网站,还是APP,人们都爱看一些新颖的视图效果.直角看多了,就想看看圆角,这几年刮起了一阵阵的圆角设计风:CSS新标准纳入圆角元素,特 ...
- Android中的ListView属性使用总结
Android中使用ListView控件比较常见,如果能知道常用的一些属性使用,肯定会少很多坑. 1.ListView是常用的显示控件,默认背景是和系统窗口一样的透明色,如果给ListView加上背景 ...
- Android中使用ListView实现自适应表格
GridView比ListView更容易实现自适应的表格,但是GridView每个格单元的大小固定,而ListView实现的表格可以自定义每个格单元的大小,但因此实现自适应表格也会复杂些(格单元大小不 ...
- android中设置ListView的选中的Item的背景颜色
ListView中没有默认的选择颜色,只有选择Item后的焦点颜色,鼠标点击时Item有颜色,放开鼠标后颜色也就没有了,要实现放开鼠标后选择项的背景还是有颜色的. 1.配置main.xml <? ...
- Android中自定义ListView实现上拉加载更多和下拉刷新
ListView是Android中一个功能强大而且很常用的控件,在很多App中都有ListView的下拉刷新数据和上拉加载更多这个功能.这里我就简单记录一下实现过程. 实现这个功能的方法不止一个,Gi ...
- 关于android中线程,进程,组件,app的理解
android系统是一座房子.有一个正常执行的公司进驻这所座子 cpu是这家公司的老板 进程是公司中的办公室,办公室不干活 线程是办公室中的员工,干活的永远是员工 一间办公室中可有多个员工,而且办公室 ...
- Android 中关于ListView分割线的设置
今天发现许多App上的listview的item之间的分割线都只显示了右边一部分,而左边的那一半则没有,第一反应则是给分割线设置一张背景图片就ok了: android:divider="@m ...
随机推荐
- Android学习路径(两)项目文件本身使用场景和文件演示
ios讨论群1群:135718460 1.src文件:java源码存放文件夹 2.gen 文件:自己主动生成全部由android开发工具自己主动生成的文件,文件夹中最重要的就是R.java文件,这个 ...
- poj Firing(最大重量封闭图)
Firing 题目: 要解雇一些人,而解雇的这些人假设人跟他有上下级的关系,则跟他有关系的人也要一起解雇.每一个人都会创造一定的价值,要求你求出在最大的获利下.解雇的人最小. 算法分析: 在这之前要知 ...
- 关于csrss.exe和winlogon.exe进程多、占用CPU高的解决办法
原地址 http://blog.sina.com.cn/s/blog_912e77480101nuif.html 最近VPS的CPU一直处在100%左右,后台管理上去经常打不开,后来发现上远程都要 ...
- android数据储存之应用安装位置
原文地址:http://developer.android.com/guide/topics/data/install-location.html#Compatiblity 从API8開始,你能够将你 ...
- 解决:对 PInvoke 函数的调用导致堆栈不对称问题
解决:对 PInvoke 函数的调用导致堆栈不对称问题 问题描述: 在使用托管代码调用非托管代码时,发生“对 PInvoke 函数“UseTwiHikVisionDllTest!UseTwiHikVi ...
- 【Cocos2d-x】Mac 在 Cocos2d-x 3.X 打包Android
今天cocos2d-x 3.0正式版最终公布了,下午特地下载了来尝尝鲜,废话不多说了. 3.0正式版的环境搭建和之前的RC版事实上是一样的,太多的教程也写了怎样搭建.今天来写写我自己是怎样来搭建的. ...
- Python调用微博API
上头叫通过微博ID获取用户公布过的历史微博内容,于是研究了下新浪微博提供的API 1 首先在微博开放中心下"创建应用"创建一个应用,应用信息那些随便填,填写完成后,不须要提交审核, ...
- SQL Server -减少代码触发的负担
触发器是一张表的增删改操作,引起或触发对还有一张表的增删改操作,所以触发器便有3种类型.各自是deleted触发器.Update触发器,insert触发器 触发器又依据替换原来的增删改操作,还是在原来 ...
- 第七章——DMVs和DMFs(1)
原文:第七章--DMVs和DMFs(1) 简介: 从SQLServer2005开始,微软引入了一个名叫DMO(动态管理对象)的新特性,DMO可以分为DMFs(Dynamic Manage Functi ...
- JEECG移动解决方案 -
针对移动应用的应用系统转换的中间件解决方案
设想: 通过中间件配置,在业务系统中使用到移动应用程序的简单版本.(移动页面生成器) 实现方法: 当前移动应用解决方式非常多:app?html5?微信 採用何种方法来实现?对于一个企业来讲,app分 ...