封装一个自动绑定View和数据的Adapter
来源:互联网 发布:discuz cms 编辑:程序博客网 时间:2024/05/22 15:53
package com.scott.uidemo.adapter;import android.content.Context;import android.graphics.Bitmap;import android.media.Image;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.AbsListView;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.LinearLayout;import android.widget.TextView;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.List;/** * author: scott * Created at scott on 2016/8/9. */public abstract class ListViewBaseAdapter<T> extends BaseAdapter { protected List<T> mDatas; protected Context mContext; protected LayoutInflater mInflater; private final String TAG = "ListViewBaseAdapter"; public ListViewBaseAdapter(List<T> datas, Context context) { mDatas = datas; mContext = context; mInflater = LayoutInflater.from(context); } @Override public int getCount() { return mDatas.size(); } @Override public Object getItem(int position) { return mDatas.get(position); } @Override public long getItemId(int position) { return position; } @Override public int getViewTypeCount() { return super.getViewTypeCount(); } @Override public int getItemViewType(int position) { return super.getItemViewType(position); } @Override public View getView(int position, View convertView, ViewGroup parent) { BaseViewHolder bVh;
//由于parent为AbsListView实例,而如果我们inflate itemView,那们itemview的 //layoutparams为GroupParams,这样会丢失itemview根布局的margin属性,所以 //在外部添加一个Linearlayout相当于加载后itemview的layoutparams为marginparams LinearLayout ll = new LinearLayout(mContext); ll.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
if (convertView == null) {
convertView = mInflater.inflate(onInflateItemView(getItemViewType(position)), ll, true); bVh = onCreateViewHolder(convertView); //保存当前itemview对应的type bVh.viewType = getItemViewType(position); convertView.setTag(bVh); } else { bVh = (BaseViewHolder) convertView.getTag(); //当当前可复用的convertview的viewtype类型和当前需要的的view的viewtype类型 //不相等时,那么无法复用该view,需要重新加载一个 if (bVh.viewType != getItemViewType(position)) { convertView = mInflater.inflate(onInflateItemView(getItemViewType(position)), ll, true); bVh = onCreateViewHolder(convertView); bVh.viewType = getItemViewType(position); convertView.setTag(bVh); } } onBindViewHolder(bVh, position); return convertView; } /*** * 当初始化ViewHolder会调用该方法,我们需要返回一个继承自BaseViewHolder * 的类的对象,该对象应该包含了itemView中我们需要的控件的实例,并且这些 * 实例已经被初始化 * * @param itemView * @return */ protected abstract BaseViewHolder onCreateViewHolder(View itemView); /*** * 当我们需要为ViewHolder中的空件设置值的时候会调用该方法,该方法中我们需要根据position为 * ViewHolder中的控件设置值 * * @param vh * @param position */ protected abstract void onBindViewHolder(BaseViewHolder vh, int position); /** * 当我们需要加载item的布局文件时会调用该方法,我们需要返回一个布局的资源ID * * @return */ protected abstract int onInflateItemView(int viewType); /*** * 所有的子类都该有一个内部的ViewHolder类继承自该类 * 继承自该类的viewholder只需将其中的view变量和对应的resId用 * BindView注解绑定即可 * * @BindView TextView tv; * 这样在onCreateViewHolder时只需new一个ViewHolder并返回即可 */ abstract class BaseViewHolder { private int viewType; View itemView; protected BaseViewHolder(View v) { itemView = v; bindView(); } /*** * 把viewholder中的view变量绑定到对应的view */ private void bindView() { //this 是runntime变量,只有在运行时才能确定 Class cls = this.getClass(); Field[] fields = cls.getDeclaredFields(); for (Field f : fields) { BindView bv = f.getAnnotation(BindView.class); if (bv == null) { continue; } f.setAccessible(true); View v = itemView.findViewById(bv.value()); try { f.set(this, v); } catch (IllegalAccessException e) { e.printStackTrace(); } } } /*** * 将当前的数据和控件绑定,但是传入的数据的类必须在类上面标识 * BindData注解,元素值可以为空 * 而类中的字段必须标识@BindData(resId)注解 * 相当于将字段值和控件绑定 * @param data */ protected void bindData(Object data) { Class cls = data.getClass(); BindData bd = (BindData) cls.getAnnotation(BindData.class); //当前传入的data没有标识BindData注解,则无法进行数据绑定 if (bd == null) { return; } Field[] fields = cls.getFields(); for (Field f : fields) { BindData bData = f.getAnnotation(BindData.class); //当前字段没有标识BindData注解则无法绑定数据 if (bData == null) { continue; } Class vCls = getClass(); Field[] vFields = vCls.getDeclaredFields(); for (Field vf : vFields) { //如果当前ViewHolder中的控件字段没有绑定资源id, //相当于没有初始化则无法绑定数据 BindView bv = vf.getAnnotation(BindView.class); if (bv == null) { continue; } f.setAccessible(true); //绑定数据 setValue(vf, f, data, bv, bData); } } } /*** * 绑定当前数据 * @param vf viewholder 中的字段 * @param f data 中的字段 * @param data 数据 * @param bv viewholder 中view字段的BindView注解对象 * @param bData Data 中的 值字段的BindData 注解对象 */ private void setValue(Field vf, Field f, Object data , BindView bv, BindData bData) { //当字段的resId 和 控件的resId 相同则进行数据绑定 //当前只支持TextView 绑定String 数据 //ImageView 绑定 Bitmap 数据 if (bv.value() == bData.value()) { if (vf.getType() == TextView.class) { try { Object o = vf.get(this); TextView tv = (TextView) o; tv.setText((String) f.get(data)); } catch (IllegalAccessException e) { e.printStackTrace(); } } if (vf.getType() == ImageView.class) { try { Object o = vf.get(this); ImageView iv = (ImageView) o; iv.setImageBitmap((Bitmap) f.get(data)); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } } /*** * 用于标识将资源id和控件进行绑定,元素不可为空 */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) protected @interface BindView { int value(); } /*** * 用于标识将数据Moudle 和 指定的资源id对应的控件进行绑定, * 元素可为空,默认为 -1, 当标识moudle类时可以为空,但标识 * 字段时不能为空,否则无法绑定 */ @Target({ElementType.FIELD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface BindData { int value() default -1; }}
利用注解反射以及baseAdapter封装了一个自动将ViewHolder中的控件和资源Id绑定,并且自动将moudle中的数据和ViewHolder中数据绑定的Adapter.
用法:
moudle
package com.scott.uidemo.moudle;import android.graphics.Bitmap;import com.scott.uidemo.R;import com.scott.uidemo.adapter.ListViewBaseAdapter;/** * author: scott * Created at scott on 2016/8/9. */@ListViewBaseAdapter.BindDatapublic class TestMoudle { @ListViewBaseAdapter.BindData(R.id.tv_content) public String data; @ListViewBaseAdapter.BindData(R.id.iv_content) public Bitmap bmp;}
adapter:
package com.scott.uidemo.adapter;import android.content.Context;import android.view.View;import android.widget.ImageView;import android.widget.TextView;import com.scott.uidemo.R;import com.scott.uidemo.moudle.TestMoudle;import java.util.List;/** * author: scott * Created at scott on 2016/8/9. */public class MyTestAdapter extends ListViewBaseAdapter<TestMoudle>{ public MyTestAdapter(List<TestMoudle> datas, Context context) { super(datas, context); } @Override protected BaseViewHolder onCreateViewHolder(View itemView) { MyHolder holder = new MyHolder(itemView); return holder; } @Override protected void onBindViewHolder(BaseViewHolder vh, int position) { TestMoudle moudle = mDatas.get(position); vh.bindData(moudle); } @Override protected int onInflateItemView(int viewType) { return R.layout.list_test_item; } final class MyHolder extends BaseViewHolder { protected MyHolder(View v) { super(v); } @BindView(R.id.tv_content) TextView tvName; @BindView(R.id.iv_content) ImageView ivName; }}
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="wrap_content" 这里的layout_width 和layout_height 以及其他的layout_xx可以直接设置,加载到listview中可以正常显示 android:orientation="vertical"> <TextView android:id="@+id/tv_content" android:text="测试文字" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ImageView android:src="@mipmap/ic_launcher" android:id="@+id/iv_content" android:layout_width="wrap_content" android:layout_height="wrap_content" /></LinearLayout>
1 0
- 封装一个自动绑定View和数据的Adapter
- Adapter的数据绑定
- view group adapter的封装
- 封装的viewholder和adapter
- 一个很好的RecyclerView的Adapter封装
- 有哪些用来绑定数据的adapter:
- 封装一个通用的 listview/gridview Adapter
- RxBinding的使用,实现数据和View的绑定
- RxBinding的使用,实现数据和View的绑定
- RxBinding的使用,实现数据和View的绑定
- Buffalo自动绑定表单Select数据的一个例子
- 封装好的万能ViewHolder和Adapter
- ListView和RecyclerView的Adapter封装
- RecyclerView中Adapter和ViewHolder的封装
- spring mvc自动封装前端发送的json数据绑定为指定对象
- Android listview 利用反射的自动绑定Adapter
- MVC中Partial View的数据绑定
- Android 一起来封装一个简单易用的Adapter
- HDU 1423 Greatest Common Increasing Subsequence(最长公共子序列+最长不下降子序列)
- DOM4J的简单介绍
- NetFlow
- grunt、gulp 的区别
- Eclipse中jsp页面报The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
- 封装一个自动绑定View和数据的Adapter
- hdu1420快速幂
- 方法的重载
- C 语言连接mysql 执行 增、删、改、查、操作
- Ping及ICMP协议
- 如何使用easywechat开发微信支付功能
- Java中Map和List组合使用的例子
- 分享在线如何将pdf转换成ppt格式
- shell编程-好玩的指令-让控制台变颜色