实现ListView适配器数据自动绑定

以前在开发Android App界面时,每使用一个ListView就要对应写一个适配器,简直痛苦万分啊。今天有空来实现在一个自动绑定数据的ListView适配器。代码的AS版本Gradle plugin 是3.5.3,Gradle是5.4.1。这代码能不能在别的版本上运行,我还真没有试过。

前提条件:

  1. 第一条也是最重要的一条,就是你已经能很熟练地做一个手动绑定的适配器。
  2. 控件命名必须有一定的规则,以方便查找。我经常命名如 txt_xxx是TextView,img_XXX是ImageView等等。
  3. 传入适配器构造函数的数据是map数组:List<Map<String,Object>> mapLists,其中每个map中的key是txt_xxx中的xxx,Obect存放要控件需要赋的数值。

思路如下:

第一步:在适配的getViewb函数中,遍历LayoutInflater生成的View,把符合条件的View都找出来存在一个List数组中,代替原来的ViewHolder保存在 View的Tag中。
第二步:在设置控件的值的地方,遍历第一步中的控件数组,给每一个控件赋值。

代码分析

我的适配器继承自BaseAdapter (其实这个无所谓,ArrayAdapter也可以),构造函数中传入的数据类型换为 List<Map<String,Object>>。适配器中除getView外,别的都没有变化。下面我们来分析getView函数。
在这个函数

@Override
public View getView(int pos, View view, ViewGroup viewGroup) {
    List<View> views=null;
    if(view==null){
        view = mLayoutInflater.inflate(R.layout.fragment_one_listview,viewGroup,false);
        views=AdapterHelper.GetViewHolder(view);
        view.setTag(views);
    }else {
        views=(List<View>)view.getTag();
    }
    AdapterHelper.SetViewValue(views,mMsgList.get(pos));
    return view;
}

首先定义一个List views来代替原来的ViewHold,在第一次加载ListVew的item资料源时,我用GetViewHolder(view)遍历view中的所有符合条件的控件(前提条件就用上了),并记录在view的Tag中。查找符合条件的代码如下:

public static List<View> GetViewHolder(View view){
    if (null == view ) {
        return null;
    }
    List<View> views = new ArrayList<>();
    if(!(view instanceof ViewGroup)){
        views.add(view);
        return views;
    }
    ViewGroup viewGroup = (ViewGroup)view;
    LinkedList<ViewGroup> linkedList = new LinkedList<>();
    linkedList.add(viewGroup);
    while (!linkedList.isEmpty()) {
        //removeFirst()删除第一个元素,并返回该元素
        ViewGroup current = linkedList.removeFirst();
        //遍历linkedList中第一个viewGroup中的子view
        for (int i = 0; i < current.getChildCount(); i++) {
            View currentView =current.getChildAt(i);
            if (currentView instanceof ViewGroup) {
                linkedList.addLast((ViewGroup) currentView);
            } else {
                if(isMustView(currentView)) {
                    views.add(current.getChildAt(i));
                }
            }
        }
    }
    return views;
}
public static final String PREFIX_TEXTVIEW="txt";
public static final String PREFIX_IMGAGEVIEW="img";
public static final String PREFIX_RADIOBUTTON="rad";
private static Boolean isMustView(View view){
    Resources resources=view.getResources();
    int id=view.getId();
    if(id==-1){
        return false;
    }
    String strViewName=resources.getResourceEntryName(view.getId());
    if(strViewName.startsWith(PREFIX_TEXTVIEW)) return true;
    if(strViewName.startsWith(PREFIX_IMGAGEVIEW)) return true;
    if(strViewName.startsWith(PREFIX_RADIOBUTTON)) return true;
    return false;
}

接下来就是重头戏了,也就是给控件赋值。我们只用循环ListView数组给每个控件赋值就可以了。代码如下。

AdapterHelper.SetViewValue(views,mMsgList.get(pos));

SetViewValue函数的代码如下:

public static void SetViewValue(List<View> views, Map<String, Object> map) {
    String strViewName="";
    for (int i = 0; i < views.size(); i++) {
        View view = views.get(i);
        if(view.getId()==-1) continue;
        strViewName = view.getResources().getResourceEntryName(view.getId());
        strViewName = strViewName.substring(4);

        if(view instanceof TextView) {
            ((TextView) view).setText(String.valueOf(map.get(strViewName)));
        } else if (view instanceof ImageView) {
            ((ImageView) view).setImageBitmap((Bitmap)map.get(strViewName));
        }else if( view instanceof RadioButton){
            ((RadioButton) view).setText(String.valueOf(map.get(strViewName)));
        }
    }
}

以下是我的这个文件全部代码:

 class Adapter_ListView extends BaseAdapter {
    private List<Map<String,Object>> mMsgList;
    private LayoutInflater mLayoutInflater;
    private Context mContext;
    public Adapter_ListView(Context context,List<Map<String,Object>> msgList) {
        this.mMsgList=msgList;
        this.mContext=context;
        mLayoutInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return mMsgList.size();
    }

    @Override
    public Map<String,Object> getItem(int i) {
        return mMsgList.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int pos, View view, ViewGroup viewGroup) {
        List<View> views=null;
        if(view==null){
            view = mLayoutInflater.inflate(R.layout.fragment_one_listview,viewGroup,false);
            views=AdapterHelper.GetViewHolder(view);
            view.setTag(views);
        }else {
            views=(List<View>)view.getTag();
        }
        AdapterHelper.SetViewValue(views,mMsgList.get(pos));
        return view;
    }

}
class AdapterHelper {
    public static final String PREFIX_TEXTVIEW="txt";
    public static final String PREFIX_IMGAGEVIEW="img";
    public static final String PREFIX_RADIOBUTTON="rad";

    public static List<View> GetViewHolder(View view){
        if (null == view ) {
            return null;
        }
        List<View> views = new ArrayList<>();
        if(!(view instanceof ViewGroup)){
            views.add(view);
            return views;
        }
        ViewGroup viewGroup = (ViewGroup)view;
        LinkedList<ViewGroup> linkedList = new LinkedList<>();
        linkedList.add(viewGroup);
        while (!linkedList.isEmpty()) {
            //removeFirst()删除第一个元素,并返回该元素
            ViewGroup current = linkedList.removeFirst();
            //遍历linkedList中第一个viewGroup中的子view
            for (int i = 0; i < current.getChildCount(); i++) {
                View currentView =current.getChildAt(i);
                if (currentView instanceof ViewGroup) {
                    linkedList.addLast((ViewGroup) currentView);
                } else {
                    if(isMustView(currentView)) {
                        views.add(current.getChildAt(i));
                    }
                }
            }
        }
        return views;
    }
    private static Boolean isMustView(View view){
        Resources resources=view.getResources();
        int id=view.getId();
        if(id==-1){
            return false;
        }
        String strViewName=resources.getResourceEntryName(view.getId());
        if(strViewName.startsWith(PREFIX_TEXTVIEW)) return true;
        if(strViewName.startsWith(PREFIX_IMGAGEVIEW)) return true;
        if(strViewName.startsWith(PREFIX_RADIOBUTTON)) return true;
        return false;
    }

    public static void SetViewValue(List<View> views, Map<String, Object> map) {
        String strViewName="";
        for (int i = 0; i < views.size(); i++) {
            View view = views.get(i);
            if(view.getId()==-1) continue;
            strViewName = view.getResources().getResourceEntryName(view.getId());
            strViewName = strViewName.substring(4);

            if(view instanceof TextView) {
                ((TextView) view).setText(String.valueOf(map.get(strViewName)));
            } else if (view instanceof ImageView) {
                ((ImageView) view).setImageBitmap((Bitmap)map.get(strViewName));
            }else if( view instanceof RadioButton){
                ((RadioButton) view).setText(String.valueOf(map.get(strViewName)));
            }
        }
    }
}

代码下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

suiyuan1211

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值