封装RecyclerView.Adapter
2016-03-28 14:04
246 查看
对RecyclerView.Adapter进行基本的封装,实现自动数据绑定。
使用泛型指定数据类型,构造是传入布局id
构造函数:
重写onCreateViewHolder方法,通过反射泛型,生成指定的ViewHolder,注意反射出来的ViewHolder需要使用指定的构造函数
重写onBindViewHolder方法,在此方法中将进行数据绑定
在bindData方法中,将根据ViewHolder的字段类型与名称,查找t中的相应数据,如果字段类型是TextView则调用setText,如果是ImageView则使用glide加载图片。注意使用此方法的前提是,ViewHolder中的字段名与JavaBean中的字段名一致。
2.Adapter
3.布局文件
使用泛型指定数据类型,构造是传入布局id
思路与实现
类声明如下:public class TRSRecyclerAdapter<T, H extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<H>
构造函数:
List<T> data; Context context; private final LayoutInflater mInflater; private int layoutId; public TRSRecyclerAdapter(List<T> data, Context context, int layoutId) { this.data = data; this.layoutId = layoutId; this.context = context; mInflater = LayoutInflater.from(context); }
重写onCreateViewHolder方法,通过反射泛型,生成指定的ViewHolder,注意反射出来的ViewHolder需要使用指定的构造函数
@Override public H onCreateViewHolder(ViewGroup parent, int viewType) { View view = mInflater.inflate(layoutId, parent, false); return getInstanceOfH(view); } H getInstanceOfH(View view) { //反射泛型 ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass(); //注意,此处的1表示泛型数组中的第二个参数。 Class<H> type = (Class<H>) superClass.getActualTypeArguments()[1]; try { //获取ViewHolder的构造方法 Constructor<H> constructor = type.getConstructor(View.class); //创建ViewHolder return constructor.newInstance(view); } catch (Exception e) { throw new RuntimeException(e); } }
重写onBindViewHolder方法,在此方法中将进行数据绑定
@Override public final void onBindViewHolder(H h, int position) { T t = data.get(position); bindData(t, h); }
在bindData方法中,将根据ViewHolder的字段类型与名称,查找t中的相应数据,如果字段类型是TextView则调用setText,如果是ImageView则使用glide加载图片。注意使用此方法的前提是,ViewHolder中的字段名与JavaBean中的字段名一致。
public void bindData(T t, H h) { setDataToHolder(t, h); } private void setDataToHolder(T t, H h) { //获取ViewHolder中的字段 Field[] fields = h.getClass().getDeclaredFields(); Object o ; //遍历字段 for (Field f : fields) { f.setAccessible(true); o = null; try { o = f.get(h); } catch (IllegalAccessException e) { e.printStackTrace(); } //判断字段类型 if (o instanceof TextView) { TextView tv = (TextView) o; //通过字段名,获取javaBean中的数据,前提是javabean中的名字与ViewHolder中的名称一样 Object value = getValueFromFiled(t, f.getName()); if (value instanceof CharSequence) { tv.setText((CharSequence) value); } } else if (o instanceof ImageView) { ImageView iv = (ImageView) o; Object value = getValueFromFiled(t, f.getName()); if (value instanceof String) { String url = (String) value; Glide.with(context).load(url).placeholder(R.drawable.default_pic).into(iv); } } } } public Object getValueFromFiled(T t, String name) { try { Field hf = t.getClass().getDeclaredField(name); hf.setAccessible(true); return hf.get(t); } catch (Exception e) { e.printStackTrace(); } return null; }
完整代码
:package trs.com.myapp.adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import trs.com.myapp.R;
/**
* Created by zhuguohui on 2016/3/23.
*/
public class TRSRecyclerAdapter<T, H extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<H>{
List<T> data;
Context context;
private final LayoutInflater mInflater;
private int layoutId;
public TRSRecyclerAdapter(List<T> data, Context context, int layoutId) {
this.data = data;
this.layoutId = layoutId;
this.context = context;
mInflater = LayoutInflater.from(context);
}
@Override
public H onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(layoutId, parent, false);
return getInstanceOfH(view);
}
H getInstanceOfH(View view) {
ParameterizedType superClass = (ParameterizedType) getClass().getGenericSuperclass();
Class<H> type = (Class<H>) superClass.getActualTypeArguments()[1];
try {
Constructor<H> constructor = type.getConstructor(View.class);
return constructor.newInstance(view);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public final void onBindViewHolder(H h, int position) {
T t = data.get(position);
bindData(t, h);
}
private void setDataToHolder(T t, H h) {
Field[] fields = h.getClass().getDeclaredFields();
Object o ;
for (Field f : fields) {
f.setAccessible(true);
o = null;
try {
o = f.get(h);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
if (o instanceof TextView) {
TextView tv = (TextView) o;
Object value = getValueFromFiled(t, f.getName());
if (value instanceof CharSequence) {
tv.setText((CharSequence) value);
}
} else if (o instanceof ImageView) {
ImageView iv = (ImageView) o;
Object value = getValueFromFiled(t, f.getName());
if (value instanceof String) {
String url = (String) value;
Glide.with(context).load(url).placeholder(R.drawable.default_pic).into(iv);
}
}
}
}
public Object getValueFromFiled(T t, String name) {
try {
Field hf = t.getClass().getDeclaredField(name);
hf.setAccessible(true);
return hf.get(t);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public void bindData(T t, H h) {
setDataToHolder(t, h);
}
@Override
public int getItemCount() {
return data == null ? 0 : data.size();
}
}
使用
1.javaBeanpackage trs.com.myapp.bean; /** * Created by zhuguohui on 2016/3/23. */ public class NewsItem { private String title; private String image; private String time; private String url; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getImage() { return image; } public void setImage(String image) { this.image = image; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } }
2.Adapter
package trs.com.myapp.adapter; import android.content.Context; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import java.util.List; import trs.com.myapp.R; import trs.com.myapp.bean.NewsItem; import trs.com.myapp.holder.TRSViewHolder; /** * Created by yuelin on 2016/3/23. */ public class NewsAdapter extends TRSRecyclerAdapter<NewsItem,NewsAdapter.NewsViewHolder> { public NewsAdapter(List<NewsItem> data, Context context) { super(data, context, R.layout.item_news_layout); } public static class NewsViewHolder extends TRSViewHolder{ public TextView title; public TextView time; public ImageView image; public NewsViewHolder(View itemView) { super(itemView); } } }
3.布局文件
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/card_view" android:layout_width="match_parent" android:layout_height="130dp" android:layout_gravity="center" app:cardCornerRadius="4dp" app:cardElevation="5dp" app:cardPreventCornerOverlap="true" app:cardUseCompatPadding="true"> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/item_news_bg" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" android:orientation="horizontal" android:padding="10dp"> <ImageView android:id="@+id/image" android:layout_width="0dp" android:layout_height="fill_parent" android:layout_gravity="top" android:layout_marginRight="10dp" android:layout_weight="5" android:scaleType="centerCrop" android:src="@drawable/default_pic" /> <RelativeLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="10" android:orientation="vertical" android:paddingRight="10dp"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:maxLines="2" android:tag="trs_text_color_black" android:text="这是标题这是标题这是标题这是标题这是标题这是标题这是标题这是标题这是标题" android:textColor="@color/primary_text" /> <TextView android:id="@+id/txt_news_summary" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:tag="trs_text_color_grey" android:visibility="gone" /> <TextView android:id="@+id/time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginTop="3dp" android:tag="trs_text_color_grey" android:text="2016-02-01" android:textColor="@color/primary" /> </RelativeLayout> </LinearLayout> </android.support.v7.widget.CardView>
效果
总结
通过对RecyclerView.Adapter的封装使自己对泛型,反射等有了更深的理解。使用时注意:要使用自动填充数据,自动绑定view功能,则必须让ViewHolder的字段名,javabean中的字段名,布局文件中的id一样。目前看来还是缺乏一些灵活性,等以后有好的方案在解决吧。相关文章推荐
- 告别数据线,使用无线进行真机测试
- 来段代码提提神-那些无法回避的知识点之过滤器Filter
- 强制隐藏android键盘
- Android属性动画完全解析(上),初识属性动画的基本用法
- doc命令大全(经典收藏)
- 二叉查找树的实现
- c 文件拷贝 fopen fwrite fread
- c#学习之二:多态
- Spring Security学习笔记-自定义Spring Security过滤链
- SQLite简单使用说明
- 数据库分库分表(sharding)系列(一) 拆分实施策略和示例演示
- Hibernate配置及三种Id生成策略
- Android 二维码扫描基于Google Zxing(仿微信)
- iOS NSClassFromString 详解
- Architecting Android…The clean way?
- 深入Java集合系列之三:HashMap
- 事件分发
- ionic准备之angular基础———服务provider 和 factory和service(9)
- 【Java80小白建站系列】7.系列搬家至www.java80.com/blog/index.htm
- POJ 2388(排序)