对于ListView数据的刷新大家都知道,改变Adapter的数据源,然后调用Adapter的notifyDateSetChanged()方法即可。

用的listview展示所有正在下载的内容。因为下载进度要实时更新,所以要不停的调用notifyDateSetChanged刷新数据。这样会不停的重新绘制整个listview的界面,性能开销非常大。而且如果每个item有图片的话,每个item的图片都需要重新加载,就算图片做了内存缓存,刷新一下图片也会闪一下,不停的刷新就会导致各个item的图片不停的闪,体验一点都不好。那么对于上面问题,有没有解决办法呢?当然是有的。我们可以针对某一个item进行局部更新,而不影响其它没有修改的item。那么具体如何实现的呢?

getView方法被多次调用(画面上能显示多少就会被调用多少次),并且在有获取网络图片的情况下会可能造成大量闪动或卡顿,极大的影响用户体验。

一些方法的介绍:

ListView.getFirstVisiblePosition():获取第一个可见的item
ListView.getLastVisiblePosition():获取最后一个可见的item

ListView.getItemAtPosition(position):获取item数据集
Adapter.getItem(position):获取item数据集,等同上面方法

ListView.getChildAt(position):获取到的是当前可见的第position项的itemview,获取的时候还需要做一个位置计算。

Adapter.getView(position, itemView , ListView ):刷新单个itemview界面

adapter.notifyDataSetChanged():是对listview的所有可见item(最上面和最下面半个也算)进行刷新,初始化listview或者手动调用此方法时都会调用getView且次数为item的可见个数。

listView.getAdapter():获取listview的adapter

实现原理:

(1)找到需要更新的item在adapter中的位置;
(2)更新adapter中item的数据data;
(3)如果该item在listView当前屏的可见范围内,则更新内容,否则不需要更新,待下次adapter刷新全部时再刷新;

更新方式:

方式1、获取itemview里的控件直接设置

View view = mListView.getChildAt(targetIndex - startShownIndex);TextView textView = (TextView) view.findViewById(R.id.textView);textView.setText(datas.get(targetIndex));

方式2、获取itemview然后调用getview方法

View view = mListView.getChildAt(targetIndex - startShownIndex);                      myAdapter.getView(targetIndex, view, mListView);//核心方法

方式3、直接更新listview的所有item

myAdapter.notifyDataSetChanged();//核心方法

demo如下:

package com.example.draggridview;import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;import java.util.ArrayList;
import java.util.List;/*** Created by Administrator on 2017/6/19.*/public class MyActivity extends AppCompatActivity {private ListView mListView;private List<String> datas;private MyAdapter myAdapter;private Button btn,btn1, btn2;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_my);datas = new ArrayList<>();for (int i = 0; i < 20; i++) {datas.add(i + "");}mListView = (ListView) findViewById(R.id.listview);btn1 = (Button) findViewById(R.id.btn1);btn2 = (Button) findViewById(R.id.btn2);btn = (Button) findViewById(R.id.btn);myAdapter = new MyAdapter(MyActivity.this, datas);mListView.setAdapter(myAdapter);btn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//1、找到item内容为5的positionString targetString = "5";int targetIndex = -1;for (int j = 0; j < mListView.getCount(); j++) {//通过listView获取item的数据集,等同于baseAdapter的getItem方法String itemString = mListView.getItemAtPosition(j).toString();if (targetString.equals(itemString)) {targetIndex = j;break;}}if (targetIndex >= 0) {//2、改变它的数据集datas.set(targetIndex, "改变!!!!");//3、可见时调用setText刷新界面int startShownIndex = mListView.getFirstVisiblePosition();int endShownIndex = mListView.getLastVisiblePosition();if (targetIndex >= startShownIndex && targetIndex <= endShownIndex) {View view = mListView.getChildAt(targetIndex - startShownIndex);TextView textView = (TextView) view.findViewById(R.id.textView);textView.setText(datas.get(targetIndex));}}}});btn1.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//1、找到item内容为8的positionString targetString = "8";int targetIndex = -1;for (int j = 0; j < mListView.getCount(); j++) {//通过listView获取item的数据集,等同于baseAdapter的getItem方法String itemString = mListView.getItemAtPosition(j).toString();if (targetString.equals(itemString)) {targetIndex = j;break;}}if (targetIndex >= 0) {//2、改变它的数据集datas.set(targetIndex, "改变!!!!");//3、可见时调用getView刷新界面int startShownIndex = mListView.getFirstVisiblePosition();int endShownIndex = mListView.getLastVisiblePosition();if (targetIndex >= startShownIndex && targetIndex <= endShownIndex) {View view = mListView.getChildAt(targetIndex - startShownIndex);
//                        mListView.getAdapter().getView(targetIndex, view, mListView);myAdapter.getView(targetIndex, view, mListView);//核心方法}}}});btn2.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//1、找到item内容为2的positionString targetString = "2";int targetIndex = -1;for (int j = 0; j < mListView.getCount(); j++) {//通过listView获取item的数据集,等同于baseAdapter的getItem方法String itemString = mListView.getItemAtPosition(j).toString();if (targetString.equals(itemString)) {targetIndex = j;break;}}if (targetIndex >= 0) {//2、改变它的数据集datas.set(targetIndex, "改变!!!!");//3、可见时调用getView刷新界面int startShownIndex = mListView.getFirstVisiblePosition();int endShownIndex = mListView.getLastVisiblePosition();if (targetIndex >= startShownIndex && targetIndex <= endShownIndex) {myAdapter.notifyDataSetChanged();//核心方法}}}});mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {//参数:listview,listview的item布局,位置,ID@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {//数据集的变化datas.set(position, "这是被更新的数据哦");//滚动看不见之后再次可见时会显示这条数据if (position != datas.size() - 1) {datas.set(position + 1, "这是被更新的数据哦,但是不展示");}//方法一//通过listview的item拿到TextView来更新控件数据//TextView testView = (TextView) view.findViewById(R.id.textView);//testView.setText(datas.get(position));//方法二//通过调用getview来更新整个itemmyAdapter.getView(position, view, mListView);//方法三//通过调用notifyDataSetChanged来更新整个listView//myAdapter.notifyDataSetChanged();//ID和position一样的值Log.e("MainActivity", "position==" + position);Log.e("MainActivity", "id==" + id);//ListView.getItemAtPosition(position)等价于Adapter.getItem(position)Log.e("MainActivity", "getItemAtPosition==" + mListView.getItemAtPosition(position).toString());}});}}

activity_my.xml

<?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"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MyActivity"><Button
        android:id="@+id/btn"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="setText改变字符串为5的item!!!"android:textSize="25sp" /><Button
        android:id="@+id/btn1"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="getView改变字符串为8的item!!!"android:textSize="25sp" /><Button
        android:id="@+id/btn2"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="notifyDataSetChanged改变字符串为2的item!!!"android:textSize="25sp" /><ListView
        android:id="@+id/listview"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1" /></LinearLayout>

MyAdapter.java

package com.example.draggridview;import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;import java.util.List;/*** Created by Administrator on 2017/6/19.*/public class MyAdapter extends BaseAdapter {private Context mContext;private List<String> datas;public MyAdapter(Context context, List<String> datas) {this.mContext = context;this.datas = datas;}@Overridepublic int getCount() {return datas == null ? 0 : datas.size();}@Overridepublic Object getItem(int position) {return datas.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder viewHolder = null;if (convertView == null) {convertView = LayoutInflater.from(mContext).inflate(R.layout.item_adapter, null);viewHolder = new ViewHolder();viewHolder.mTextView = (TextView) convertView.findViewById(R.id.textView);convertView.setTag(viewHolder);} else {viewHolder = (ViewHolder) convertView.getTag();}viewHolder.mTextView.setText(datas.get(position));Log.e("MainActivity", "getView  position==" + position);return convertView;}class ViewHolder {private TextView mTextView;}}

item_adapter.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextView
        android:id="@+id/textView"android:layout_width="match_parent"android:layout_height="60dp"android:gravity="center"android:textSize="45sp"android:text="1" /></LinearLayout>

测试结果:

1、直接设置setText:不会调用getView方法
2、获取itemview然后调用adapter.getview方法:只调用一次当前position的getview方法。
3、notifyDataSetChanged:会调用所有可见item的getview方法

参考:

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

Android RecyclerView与ListView局部刷新

ListView实现Item局部刷新

面试 – ListView对其指定的子Item进行单独的刷新

listview局部刷新

ListView中单独更新某个Item的方法

ListView高效刷新——刷新单条数据相关推荐

  1. android 在自定义的listview(有刷新加载项)列表中,数据过少时不能铺满整个屏幕时,header和footer同时显示问题...

    android  在自定义的listview(有刷新加载项)列表中,数据过少时,当刷新时,加载项也会显示,这是很头疼的一个问题,查阅了一些资料,总结了一个比较不错的方法: 原来代码: 1 @Overr ...

  2. 关于ListView中notifyDataSetChanged()刷新数据不更新原因

    使用Listview的时候: 当要动态显示更改后的 数据 (例如 数据 库改动), 很多人应该都用过notifyDataSetChanged();这个方法来刷新Listview,显示改后的 数据 . ...

  3. Flutter 21: 图解 ListView 下拉刷新与上拉加载 (三)【RefreshIndicator】

    小菜前段时间整理了两种 ListView 的异步加载数据时,下拉刷新与上滑加载更多的方式,每种方式都有自己的优势,网上也有很多大神讲解过 ListView 数据流的种种处理方式,小菜根据实际遇到的情况 ...

  4. Flutter开发之ListView下拉刷新上拉加载更多(35)

    在Flutter开发之ListView组件(21) 文章中,我们了解了ListView组件的基本使用.但是数据比较少,没有涉及分页加载.而实际开发中,下拉刷新和分页加载几乎是所有APP的标配.在iOS ...

  5. ListView下拉刷新、上拉载入更多之封装改进

    在Android中ListView下拉刷新.上拉载入更多示例一文中,Maxwin兄给出的控件比较强大,前面有详细介绍,但是有个不足就是,里面使用了一些资源文件,包括图片,String,layout,这 ...

  6. Flutter ListView 下拉刷新与上拉加载更多

    ListView 下拉刷新与上拉加载更多 import 'dart:async'; import 'package:flutter/material.dart';/*** 有状态StatefulWid ...

  7. Android学习之——ListView下拉刷新

    背景知识 ListView使用非常广泛,对于使用ListView的应用来说,下拉刷新是必不可少要实现的功能. 我们常用的微博.网易新闻,搜狐新闻都使用了这一功能,如下图所示.     微博 搜狐新闻 ...

  8. android中上拉下滑布局,3年以上勿进!最简单的Android自定义ListView下拉刷新与上拉加载,代码直接拿去用~...

    本文主要针对开发新手,手写实现一个最简单Android自定义listview下拉刷新和上拉加载demo. 不喜可喷,欢迎大佬留言指点. 效果图 一:编写需要在ListView中增加头加载的布局文件,与 ...

  9. Android 自定义 ListView 上下拉动“刷新最新”和“加载更多”歌曲列表

    本文内容 环境 测试数据 项目结构 演示 参考资料 本文演示,上拉刷新最新的歌曲列表,和下拉加载更多的歌曲列表.所谓"刷新最新"和"加载更多"是指日期.演示代码 ...

最新文章

  1. mysqlbinlog工具_mysqlbinlog命令详解 Part 1-实验环境准备
  2. 代码走查和代码审查_如何避免代码审查陷阱降低生产率
  3. c语言调用的viod函数不执行,void 函数 调用问题
  4. 搜索 —— 启发式搜索 —— 模拟退火
  5. SQL Server群集共享存储迁移
  6. TensorFlow tf.squeeze
  7. Maven学习总结(43)——利用javadoc插件生成项目的API文档
  8. CentOS7虚拟机克隆,且成功互ping
  9. ionic创建应用的三个模版
  10. html英文特殊字体代码,字体_中英文字体等(示例代码)
  11. 深入浅出:Java多线程编程实战(一)
  12. 第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛.J强迫症的序列
  13. KiCad快速修改PCB线宽
  14. Centos Web Proxy(nginx)配置
  15. Fusion APP-添加检查软件更新功能
  16. CSS实现长宽比的几种方案,CSS如何实现长宽比?
  17. 【C++】火车站的列车调度
  18. h5难做吗_欢庆网:对于H5,可能没你想的那么难!
  19. 「区块链+数字身份」:DID 身份认证的新战场
  20. matlab:变计算精度函数vpa,digits

热门文章

  1. Fortran编译器
  2. 百趣代谢组学分享,膜脂代谢对桃果实冷藏过程中冷害的影响
  3. java 冒泡排序 选择排序 插入排序及其异同点
  4. 主数据的3个特点、4个超越和3个二八原则
  5. (转)用InternetOpen下载小文件 vc c++
  6. 社交向左,AI当立;岁在戊戌,腾讯大急!
  7. 2021年电工(初级)考试试卷及电工(初级)试题及答案
  8. linux之fdisk命令
  9. 想在网上兼职做什么比较好,分享五个网上兼的副业项目帮你拓展视野
  10. 找出所有不是这两个数组共有的元素