1.数据更新
前面介绍了listView的数据绑定,在getView()方法中对组件设置值的时候,无论有无数据都需要对其赋值,有则赋值为数据内容,否则手动恢复默认状态,防止重用而导致显示错乱。
那么,数据更新也是常用的,例如,点击按钮改变文字内容,或者点击某一行进入另外一个页面,亦或者长按之后弹出一个选项框,等等。
2.适配器刷新
适配器的加载决定lsitView最终显示的内容。
2.1全部刷新
调用adapter的 notifyDataSetChanged();可以让adapter重新加载当前显示的行的数据。例如屏幕上仅显示了4567项,则仅加载4567的数据( 就算只显示了一条边也算显示项),重新加载就会使adapter调用getView()方法。
示例如下:
mainActivity中写上listView的行点击事件
//行点击事件 lv.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
list.set(position,"行修改"); adapter.notifyDataSetChanged();}}) ;
在adapter中为按钮设置点击事件,代码如下:
holder.bt.setOnClickListener(new MyClick(position));
其中click事件写成了类,这样写的好处是可以传递参数并分离getView的代码,让getView的代码变得小一些。
你可以把类独立写成一个java文件,也可以写在adapter文件里面编程adapter的内部类
其他一些例如一些大面积设置的代码也可以写成方法并传递position和viewholder,在方法中进行处理。
一些动态适配的代码若每一行都是一样的则可以放在最开始声明View的if块里(当然,写成一个方法然后调用)。
这样后期维护的时候,代码就比较好改了,否则一旦getView代码几百上前行,鼠标的滑轮会哭的。
class MyClick implements View.OnClickListener { private int click_position; public MyClick(int click_position) { this.click_position = click_position; } @Override public void onClick(View view) { list.set(click_position,"修改"); notifyDataSetChanged(); } }
若你需要同时设置listView的行点击事件和每一行按钮的点击事件,那么在list_item.xml的根布局下加上一条属性即可
android:descendantFocusability="blocksDescendants"
按钮会抢占,listView的焦点使得listView无法响应行点击事件或长按事件等等。一个一个的将item的按钮的焦点设为false太麻烦,
2.2,局部刷新
全部刷新会导致一些没必要刷新的内容被刷新,当数据量比较小或者每行的内容比较少的时候,使用全部刷新是没有问题的。但数据量多了或是每行的内容较多的时候,再全部刷新则会导致listView卡顿
使用view或者viewHolder进行刷新将不会让适配器全部刷新。
获取view和viewHolder的方式:
/** * 单独更新组件 * @param position * 更新组件的下标 */ public void updateData(int position){ //获取当前显示项的第一行和最后一行 int firstVisible = lv.getFirstVisiblePosition(); int lastVisible = lv.getLastVisiblePosition(); //获取该行的view(因为listView仅会维护当前的显示项,所以根据下标获取时,0为当前显示行 // 的第一行即firstVisible,所以获取当前行应该用当前行减去firstVisible) View view = lv.getChildAt(position - firstVisible); if(view != null){ //若获取的时候该行被滑出屏幕则会返回空 //获取viewHolder // ViewHolder holder = (ViewHolder) view.getTag(); // holder.tv.setText("change"); //若不使用ViewHolder,也可以直接使用view TextView tv = (TextView) view.findViewById(R.id.item_textView); tv.setText("change"); }
备注:1.测试:通过在getView的第一行写输出语句输出position即可观察修改时getView的调用情况
2单独刷新:单独刷新的时候,注意不要让xml文件中的listView的宽高为wrap_content,因为wrap_content会在开始的时候绘制一次,显示之前根据子组件再绘制一次(即使没有什么改变),这时的绘制将使adapter调用notify使局部更新看上去失效了。