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的时候,应该是白色(默认为白色)
运行项目发现,当上下滑动时,一些行使用了复用信息,但没有对该信息进行处理直接显示,导致背景色同样变成了蓝色
连续上下滑动效果将会更加明显。
实际运行过程为:
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中对一个组件赋值时,若有数据则赋值为数据内容,若没有数据则手动重置该组件内容,防止因为重用的关系导致数据错乱