android开发-自定义listView-(以及由于自身编写错误导致的bug修复)

自定义ListView实践
本文介绍了一个自定义ListView的实现过程,包括如何创建适配器、ViewHolder模式的应用以及常见bug的解决方法。通过示例代码展示了如何正确绑定数据,避免因初始化错误导致的显示异常。

android开发-自定义listView-(以及由于自身编写错误导致的bug修复)

前言

近期的项目里需要用listView去显示用户列表,自带的功能不足以满足我的设计需求,于是我就各方面学习了一下怎么制作一个自定义listView。并且也在开发过程中自己写错了代码因此特意记录引以为戒。
特别提示:下方演示代码仅适配我的设计需求,并且只摘录了核心代码,使用时需要根据自身需求做出适当改变

核心代码块1 - MyListAdapter

class MyListAdapter extends BaseAdapter {

    private Context mContext;

    private ArrayList<MyOwnerFaceListInfo> beans;

    public MyListAdapter() {
        ;
    }
    public MyListAdapter(Context mContext) {
        this.mContext = mContext;
    }

    public MyListAdapter(ArrayList<MyOwnerFaceListInfo> beans, Context mContext) {
        this.beans = beans;
        this.mContext = mContext;
    }

    @Override
    public int getCount() {
        if(beans == null) {
            return 0;
        }
        return beans.size();
    }

    @Override
    public Object getItem(int position) {
        return beans.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if(beans == null) {
            return null;
        }
        ViewHolder vh = null;
        if (convertView == null ) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.list_bean_layout, null);//lins
            vh = new ViewHolder();
            vh.tv1=(TextView)convertView.findViewById(R.id.list_textView1);
            vh.tv2=(TextView)convertView.findViewById(R.id.list_textView2);
            vh.iv1=(ImageView)convertView.findViewById(R.id.list_imageView1);
//            String userID   = beans.get(position).Name;
//            String userDate = beans.get(position).Date;
//
//            vh.tv1.setText(userID);
//            if(beans.get(position).FaceBitmap != null)
//                vh.iv1.setImageBitmap(beans.get(position).FaceBitmap);
//            vh.tv2.setText(userDate);
            convertView.setTag(vh);
        }else {
            vh = (ViewHolder)convertView.getTag();
        }

        String userID   = beans.get(position).Name;
        String userDate = beans.get(position).Date;

        vh.tv1.setText(userID);

        vh.iv1.setImageBitmap(beans.get(position).FaceBitmap);
        vh.tv2.setText(userDate);


//      绑定数据
        //viewHolder.textView.setText(listData.get(position));
        return convertView;
    }
    public static class ViewHolder{
        TextView  tv1;
        TextView  tv2;
        ImageView iv1;
    }
}

概述-以及bug代码

这部分代码里类MyOwnerFaceListInfo为我自定义的类,用于存放每个item所需的元素,基本如下:

class MyOwnerFaceListInfo {
    public Bitmap FaceBitmap = null;
    public String Name = null;
    public String Date = null;
    //------------------------
    public MyOwnerFaceListInfo(String name,Bitmap faceBitmap){
        Name = name;
        FaceBitmap = faceBitmap;
    }
}

上述代码中其他部分不需要在意,重点在于getView函数里的内容,里面用了ViewHolder这个机制节约了内存和使用时间,并且这部分我之前写错误了,我将数据初始化写在了视图初始化的部分里,也就是我上方代码注释的那一部分,导致了我显示时出现了超出屏幕范围的item数据加载错误的情况。

bug区域原始写法
if (convertView == null ) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.list_bean_layout, null);//lins
            vh = new ViewHolder();
            vh.tv1=(TextView)convertView.findViewById(R.id.list_textView1);
            vh.tv2=(TextView)convertView.findViewById(R.id.list_textView2);
            vh.iv1=(ImageView)convertView.findViewById(R.id.list_imageView1);
            String userID   = beans.get(position).Name;
            String userDate = beans.get(position).Date;

            vh.tv1.setText(userID);
            if(beans.get(position).FaceBitmap != null)
                vh.iv1.setImageBitmap(beans.get(position).FaceBitmap);
           vh.tv2.setText(userDate);
           }

这是由于采用了ViewHolder时,系统仅会对屏幕上显示的item做初始化和数据绑定,而超出屏幕范围的item采用的方法是继承移出屏幕的数据存放空间也就是继承convertView,而每一个item将显示时都会执行getView进行初始化,我的编写错误导致需要被加载的部分数据不能被初始化,因此出现了移出屏幕和移入屏幕的item数据错误的现象
引以为戒

核心代码块2 - list_bean_layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="#FFF"
    android:gravity="center"
    >


    <ImageView
        android:layout_margin="10dp"
        android:id="@+id/list_imageView1"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:src="@android:drawable/ic_menu_my_calendar"
        android:background="#000"
        />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:gravity="center"
        >

        <TextView
            android:id="@+id/list_textView1"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="35dp"
            android:text="abababababa"
            android:layout_margin="5dp"
            android:textColor="#000"
            />

        <TextView
            android:id="@+id/list_textView2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="tip:ababababa"
            android:textSize="25dp"
            android:layout_marginLeft="20dp"
            android:textColor="#444"
            />
    </LinearLayout>

</LinearLayout>

概述

这部分是自定义item,通过自定义要显示的list的元素的布局实现自身的设计。
对应绑定的代码为:
convertView = LayoutInflater.from(mContext).inflate(R.layout.list_bean_layout, null);//lins
如果有自身的特殊设计需求,可以设计多个不同的布局,让每一行显示不同的设计

应用

//获取布局里的控件
mListView = (ListView) findViewById(R.id.dialog_list);
//初始化list适配器
myListAdapterOwner = new MyListAdapter(myOwnerList,context);
//为listView绑定适配器
mListView.setAdapter(myListAdapterOwner);

概述

使用是核心代码就这么3句。
其中决定显示内容的最后一句,因此如果想让list根据情况使用不同的数据模式,也可以通过自定义不同的适配器模型,然后通过绑定适配器的方式来决定显示内容。
自定义的适配器里的数据需要在绑定前完成初始化,也就是如果后续修改了list数据,如果想要这部分数据在listView里生效,则需要重新.setAdapter

结语

我的代码库里缺少一个自定义listView的模板,目前也补上了,以上代码已经切实证明可行,后续开发可以以此作为借鉴。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值