安卓开发,listView相关(四),数据绑定

1.数据绑定介绍

之前介绍了使用ViewHolder机制,使用复用的View来节省重复加载组件损耗的资源,可以让listView显示的更为流畅。
复用的实际意义是将整个view(可以理解为布局以及布局上的内容)一起拿过来使用,在这个状态下,若没有进行处理而直接显示会造成我们不希望看到的情况。例如第一行显示了一张图片,上下滑动之后第七行也显示了第一行的图片,而它本身的图片却不见了。诸如图片,背景,进度条等等。


2.绑定数据说明

状况重现:修改之前的项目,为list_item.xml的根节点添加一个id属性
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:id="@+id/item_root"
    android:layout_height="60dp">

    <TextView
        android:id="@+id/item_textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true" />

    <Button
        android:id="@+id/item_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:text="点击" />
</RelativeLayout>

将根节点添加到viewholder中,并修改getView()方法
/***
 * ViewHolder
 * 在这里声明所有即在getView方法使用的组件
 */
class ViewHolder {
    TextView tv;
    Button bt;
    RelativeLayout root;
}
/**
 * 创建并返回每一条信息的实际内容
 *
 * @param position  当前创建并返回的是第几条信息
 * @param view      当前布局内容,当前复用的布局
 * @param viewGroup
 * @return
 */
@Override
public View getView(final int position, View view, ViewGroup viewGroup) {
    //声明ViewHolder
    ViewHolder holder;
    //当view为空的时候,说明当前行没有可以使用的复用信息,则创建一个
    if (view == null) {
        //加载刚才为适配器写的布局
        view = inflater.inflate(R.layout.list_item, viewGroup, false);
        //初始化viewHolder对象
        holder = new ViewHolder();
        //给组件赋值
        holder.tv = (TextView) view.findViewById(R.id.item_textView);
        holder.bt = (Button) view.findViewById(R.id.item_button);
        holder.root = (RelativeLayout) view.findViewById(R.id.item_root);
        //保存tag
        view.setTag(holder);
    }else   //如果有可复用的信息,则直接获取
        holder = (ViewHolder) view.getTag();
    //根据数据源内容设置文本内容
    holder.tv.setText(list.get(position));
    holder.bt.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Toast.makeText(context,"点击"+position,Toast.LENGTH_SHORT).show();
        }
    });
    if(position < 3)
        holder.root.setBackgroundColor(Color.BLUE);
    //注意返回view,若返回null则上面的代码都不会生效
    return view;
}

上面的代码中,当position < 3的时候,为根节点设置一个蓝色的背景色,那么当position >= 3的时候,应该是白色(默认为白色)

运行项目发现,当上下滑动时,一些行使用了复用信息,但没有对该信息进行处理直接显示,导致背景色同样变成了蓝色
连续上下滑动效果将会更加明显。
图片示例1示例图片2

实际运行过程为:
item0被加载,view为空,运行if内的内容,因为position <3,背景被设置为蓝色。
当item0被滑出屏幕的时候,被做为复用项,赋值给了view,
item11被加载时,view不为空,跳过if直接获取tag,因为position >= 3 ,没有对背景进行任何操作
所以当item11最终显示出来的时候,背景成为了蓝色

修改getView()中的代码:
if(position < 3)
    holder.root.setBackgroundColor(Color.BLUE);
else
    holder.root.setBackgroundColor(Color.WHITE);

再次运行项目即可发现恢复正常


总结:

实际项目中,在getView中对一个组件赋值时,若有数据则赋值为数据内容,若没有数据则手动重置该组件内容,防止因为重用的关系导致数据错乱

猜你喜欢

转载自blog.csdn.net/qq_26559913/article/details/53816330