概述

在使用ListView的时候,我们都会对列表数据进行更新,当数据变化时,我们会调用adapter的notifyDataSetChange方法去刷新列表。但是,该刷新方法是使整个列表都更新一遍(调用了adapter的getView方法)。而,我们往往只是更新了item中的某一项数据,如果刷新整个列表是不是显得太过于浪费了,特别是对于列表中有图片要显示的情况下,就会造成每次notifyDataSetChange图片会闪烁抖动。本文意在解决该问题,让数据更新只在局部。

解决方案

  • 情景再现

下面例子的效果是,列表数据显示的是一系列数字,点击列表的item项时,该列表数字加1。那么一般的代码实现如下:
定义一个adapter

MyAdapter.java

public class MyAdapter extends BaseAdapter{private Context context;private List<Integer> datas;public MyAdapter(Context context,List<Integer> datas){this.context = context;this.datas = datas;}@Overridepublic int getCount() {if(datas != null){return datas.size();}return 0;}@Overridepublic Integer getItem(int position) {return datas.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if(convertView == null){convertView = LayoutInflater.from(context).inflate(R.layout.item_adapter,parent,false);holder = new ViewHolder();holder.textView = (TextView) convertView.findViewById(R.id.textview);convertView.setTag(holder);}else {holder = (ViewHolder) convertView.getTag();}holder.textView.setText(String.valueOf(getItem(position)));return convertView;}private class ViewHolder{TextView textView;}
}

item 布局这里只是简单的一个TextView
item_adapter.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="wrap_content"><TextView
        android:id="@+id/textview"android:layout_width="match_parent"android:layout_height="wrap_content"android:minHeight="45dp"android:textSize="18sp"android:gravity="center"android:textColor="@android:color/black"/>
</LinearLayout>

activity的布局activity_listview.xlm

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"><ListView
        android:id="@+id/listview"android:layout_width="match_parent"android:layout_height="match_parent"/>
</LinearLayout>

数据显示

public class ListViewTest extends Activity{ListView mListView;MyAdapter adapter;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_listview);mListView = (ListView) findViewById(R.id.listview);final List<Integer> datas = new ArrayList<Integer>();for (int i=1;i<10;i++){datas.add(i);}adapter = new MyAdapter(this,datas);mListView.setAdapter(adapter);mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {int data = datas.get(position);data = data+1;datas.set(position,data);adapter.notifyDataSetChanged();}});}
}

这里主要是给ListView设置了setOnItemClickListener事件,然后进行+1处理,最后调用adapter的notifyDataSetChanged刷新数据。

好了,以上是我们一般的传统做法,下面我们看下如何实现ListView的局部刷新。

  • ListView局部刷新实现

在adapter里定义一个方法notifyDataSetChangedAt(View view,int position),然后在该方法处理逻辑
例如本例子如下:

public void notifyDataSetChangedAt(View view,int position) {if(view != null){int data = datas.get(position);data = data+1;datas.set(position,data);TextView textView = (TextView) view.findViewById(R.id.textview);textView.setText(String.valueOf(data));}}

然后在外部调用,实现调用,这里有两种场景,实现方法不同。

  • 第一种,在当前ListView点击item进行刷新
    这种场景是属于比较常规的,实现起来也是比较简单的,如下:
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {/*int data = datas.get(position);data = data+1;datas.set(position,data);adapter.notifyDataSetChanged();*/adapter.notifyDataSetChangedAt(view,position);}
});

只要在ListView的setOnItemClickListener调用adapter的notifyDataSetChangedAt即可

  • 第二种,在‘详情页’进行操作后,需要刷新ListView

第二种比较复杂一点,和业务关系紧密,一般业务场景是这样的:比如微博,在微博详情页,我点赞了,那么微博的列表相应的item的赞数要加1,这种场景的复杂在于,业务操作点与ListView脱离,不知要更新哪个item,但是,一般我们的业务module都有自己的一个id,通过该id我们就可以计算出item的位置。

修改一下adapter的数据类型,增加module

public class MyModule {private int id;private int count;public int getId() {return id;}public void setId(int id) {this.id = id;}public int getCount() {return count;}public void setCount(int count) {this.count = count;}
}

然后修改MyAdapter的数据类型为MyModule

public class MyAdapter extends BaseAdapter{private Context context;private List<MyModule> datas;public MyAdapter(Context context,List<MyModule> datas){this.context = context;this.datas = datas;}@Overridepublic int getCount() {if(datas != null){return datas.size();}return 0;}@Overridepublic MyModule getItem(int position) {return datas.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder;if(convertView == null){convertView = LayoutInflater.from(context).inflate(R.layout.item_adapter,parent,false);holder = new ViewHolder();holder.textView = (TextView) convertView.findViewById(R.id.textview);convertView.setTag(holder);}else {holder = (ViewHolder) convertView.getTag();}holder.textView.setText(String.valueOf(getItem(position).getCount()));return convertView;}private class ViewHolder{TextView textView;}/*** 局部刷新*/public void notifyDataSetChangedAt(View view,int position) {if(view != null){MyModule data = datas.get(position);data.setCount(data.getCount()+1);datas.set(position,data);TextView textView = (TextView) view.findViewById(R.id.textview);textView.setText(String.valueOf(data.getCount()));}}
}

修改activity

public class ListViewTest extends Activity{ListView mListView;MyAdapter adapter;List<MyModule> datas = new ArrayList<MyModule>();@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_listview);mListView = (ListView) findViewById(R.id.listview);for (int i=0;i<10;i++){MyModule module = new MyModule();module.setId(i);module.setCount(i+1);datas.add(module);}adapter = new MyAdapter(this,datas);mListView.setAdapter(adapter);mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {/*int data = datas.get(position);data = data+1;datas.set(position,data);adapter.notifyDataSetChanged();*///adapter.notifyDataSetChangedAt(view,position);onListViewItemClick(datas.get(position));}});}private void onListViewItemClick(MyModule myModule){//获取屏幕中ListView可见部分的第一个item位置索引final int firstPos = mListView.getFirstVisiblePosition();//循环遍历for (int i = 0; i < datas.size(); i++) {MyModule module = datas.get(i);if (myModule != null && myModule.getId() == module.getId()) {View v = mListView.getChildAt(i - firstPos);adapter.notifyDataSetChangedAt(v, i);break;}}}
}

我这里没有‘详情页’,通过ListView的ItemClickListener事件模拟了。最重要的方法是onListViewItemClick。思路:一般我们点击item进详情时,该item是处于在屏幕可见的,所以为了减少遍历次数,我们计算了ListView的第一个可见item的位置,然后通过比较是否是同一个module id实现局部刷新。

注意:一般使用场景是,详情页进行操作并更新module之后,通过setResult将module传给onActivityResult,然后调用onListViewItemClick(MyModule myModule)

ListView 局部刷新相关推荐

  1. android ListView 局部刷新

    今天,简单讲讲android如何对ListView 进行局部刷新. 之前,自己做的ListView 发现刷新频率太高了,而且很多界面上看不到的数据改变时调用Adapter.notifyDataSetC ...

  2. Flutter ListView 局部刷新数据、ListView点赞收藏

    题记 -- 执剑天涯,从你的点滴积累开始,所及之处,必精益求精. Flutter是谷歌推出的最新的移动开发框架. [x1]微信公众号的每日提醒 随时随记 每日积累 随心而过 [x2]各种系列的视频教程 ...

  3. Android ListView局部刷新item

    当前ListView页面跳转到其他页面返回后,重新获取数据后刷新局部item 1.首先需要获取到跳转之前item的位置,给ListView设置setOnScrollViewListener()接口,在 ...

  4. android:ListView的局部刷新

    1.简介 对于android中的ListView刷新机制,大多数的程序员都是很熟悉的,修改或者添加adapter中的数据源之后,然后调用notifyDataSetChanged()刷新ListView ...

  5. Android ListView优化之局部刷新(更新)(非notifyDataSetChanged)

    转载请注明出处:http://blog.csdn.net/linglongxin24/article/details/53020164 [DylanAndroid的csdn博客] 在Android开发 ...

  6. ListView高效刷新——刷新单条数据

    对于ListView数据的刷新大家都知道,改变Adapter的数据源,然后调用Adapter的notifyDateSetChanged()方法即可. 用的listview展示所有正在下载的内容.因为下 ...

  7. ListView实现item局部刷新

    原理就是获得需要刷新的item,然后重新设置item中控件的数据,其他item不变. 之所以需要用到局部刷新是因为在做项目的时候,发现在需要listview的个别item时,如果调用Adapter的n ...

  8. android 解决listview.notifyDataSetChanged刷新时Imageloader加载图片闪烁问题

    今天,简单讲讲android里再listview调用notifyDataSetChanged刷新界面时,Imageloader加载图片会闪烁的问题. 最近,发现app里的listview图片会出现闪烁 ...

  9. android局部布局刷新,Android RecyclerView 局部刷新分析

    前情回顾 之前写的 PowerAdapter 和 SelectPowerAdapter 从创建到现在,已经两年多,期间发生了翻天覆地的变化.一开始,我把 SwipeRefreshLayout 和 Re ...

最新文章

  1. python 函数变量_Python函数中的变量和函数返回值
  2. win10+VS2013+opencv2.4.11的安装和配置
  3. 在两个页面之间互相写其控件内的值
  4. leetcode 贪心_LeetCode进阶1029-贪心
  5. 最新版freetextbox(版本3.1.6)在asp.net 2.0中使用简解
  6. 21 Python模块、import语句、搜索路径、变量、命名空间和作用域、dir函数、globals()和locals()函数、reload()函数、Python中的包
  7. 函数调用基础概念原理
  8. 信息保真度准则_设计保真度的新的非科学公式
  9. 微软官方pe工具_微软官方下载工具
  10. IA-32 Architecture: the function of segment regitster(CS DS SS ES)
  11. C++primer 第 4 章 表达式 4.7条件运算符 4.8位运算符 4.9 sizeof运算符 4.10逗号运算符 4.11类型转换 4 . 1 2 运算符优先级表
  12. 【C语言】复合函数求值
  13. ShadeGraph教程之节点详解1:Artistic Nodes
  14. html绘制圆形和弧形的代码,html5 canvas用来绘制弧形的代码实现
  15. Java 转换EXCEL Duble格式时间为指定格式日期字符串
  16. 重估维信金科:担保压身,负重难行
  17. Python 解多元高次方程
  18. mysql添加用户并赋予权限命令
  19. CISCO banner MOTD, Login的区别
  20. 子之错父之过什么意思_生活|为什么子不教,父之过,这是什么意思?

热门文章

  1. 人体工学电脑椅选购建议
  2. 基于Android的电影选座订票系统毕业设计源码011439
  3. Unity解析OpenDRIVE地图数据,并生成路网模型
  4. 基准点定位-精度测试
  5. BindingException 绑定异常
  6. 基于windows的mongodb安装及mongovue可视化连接使用
  7. android emulator ps4,PS4 Simulator手机版
  8. java分页搜索接口
  9. Java常见异常种类及产生原因
  10. deepin linux 2014安装,2014.2版本的Deepin虚拟机安装浅谈(就是深度Linux)