ViewPager的PagerAdapter中的notifyDataSetChanged更新数据总结

article/2025/9/23 0:11:27

最近在工作中遇到了一个问题,就是在viewpager中调用pageradapter.notifydatasetchanged方法,好像没有任何效果,相应的view也没有更新数据,根据官方API是这样解释的:大概是说明Adapter会自动管辖ViewPager每一页(Item)的状态,而notifyDataSetChanged()是用在当ViePager要新增一页、刪除一页或改变各个页面的排列的時候。所以ViewPager Adapter的notifyDataSetChanged自然就不适用于只更新View Pager里面某个View的內容的需求。

通常的解决方案是重写 PagerAdapter 的 getItemPosition() 方法,并返回 POSITION_NONE ,以触发 PagerAdapter 销毁并重建对象。

下面我们通过源代码分析为什么必须 override这个方法。

首先看 PagerAdapter 源代码,它的 notifiDataSetChanged() 方法内部调用了一个 DataSetObservable 对象的 notifyChanged() 方法:

/**
* This method should be called by the application if the data backing this adapter has changed
* and associated views should update.
*/
public void notifyDataSetChanged() {
mObservable.notifyChanged();
}

跟进这个方法,我们找到DataSetObservable的notifyChanged方法:

/**
* Invokes {@link DataSetObserver#onChanged} on each observer.
* Called when the contents of the data set have changed.  The recipient
* will obtain the new contents the next time it queries the data set.
*/
public void notifyChanged() {
synchronized(mObservers) {
// since onChanged() is implemented by the app, it could do anything, including
// removing itself from {@link mObservers} - and that could cause problems if
// an iterator is used on the ArrayList {@link mObservers}.
// to avoid such problems, just march thru the list in the reverse order.
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
}
}
}

mObservers的类型是一个抽象类DataSetObserver,里面只有两个为实现的方法:

/**
* Receives call backs when a data set has been changed, or made invalid. The typically data sets
* that are observed are {@link Cursor}s or {@link android.widget.Adapter}s.
* DataSetObserver must be implemented by objects which are added to a DataSetObservable.
*/
public abstract class DataSetObserver {
/**
* This method is called when the entire data set has changed,
* most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
*/
public void onChanged() {
// Do nothing
    }
/**
* This method is called when the entire data becomes invalid,
* most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a
* {@link Cursor}.
*/
public void onInvalidated() {
// Do nothing
    }
}

都有谁使用了这个抽象类呢,ctrl+T可以查看调用者

image

进入viewpager,找到控制数据更新的重点代码:

void dataSetChanged() {
// This method only gets called if our observer is attached, so mAdapter is non-null.
boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1 &&
mItems.size() < mAdapter.getCount();
int newCurrItem = mCurItem;
boolean isUpdating = false;
for (int i = 0; i < mItems.size(); i++) {
final ItemInfo ii = mItems.get(i);
final int newPos = mAdapter.getItemPosition(ii.object);
//根据getItemPosition的返回值,来决定是否调用destroyItem方法。
            if (newPos == PagerAdapter.POSITION_UNCHANGED) {
continue;
}
if (newPos == PagerAdapter.POSITION_NONE) {
mItems.remove(i);
i--;
if (!isUpdating) {
mAdapter.startUpdate(this);
isUpdating = true;
}
mAdapter.destroyItem(this, ii.position, ii.object);
needPopulate = true;
if (mCurItem == ii.position) {
// Keep the current item in the valid range
newCurrItem = Math.max(0, Math.min(mCurItem, mAdapter.getCount() - 1));
needPopulate = true;
}
continue;
}
if (ii.position != newPos) {
if (ii.position == mCurItem) {
// Our current item changed position. Follow it.
newCurrItem = newPos;
}
ii.position = newPos;
needPopulate = true;
}
}
if (isUpdating) {
mAdapter.finishUpdate(this);
}
Collections.sort(mItems, COMPARATOR);
if (needPopulate) {
// Reset our known page widths; populate will recompute them.
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (!lp.isDecor) {
lp.widthFactor = 0.f;
}
}
setCurrentItemInternal(newCurrItem, false, true);
requestLayout();
}
}

从上面我们看到,它会判断adapter的getItemPosition方法的返回值,只有当返回值是POSITION_NONE时候,才会调用item的remove方法以及startUpdate和destroyItem方法,进而去更新数据。默认返回值是POSITION_UNCHANGED,不执行任何操作。

PagerAdapter 的 getItemPosition() 方法的默认实现:

public int getItemPosition(Object object) {
return POSITION_UNCHANGED;
}

看到这里,大家基本就可以理解为什么我们要覆盖这个方法了。这个方法很简单,但是每次调用adapter都会去调用destroy方法,因此最好是自己做view的缓存,destroy方法可以默认不处理,下面贴上简单实现:

@Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }

@Override
public Object instantiateItem(View container, int position) {
//下面是我自己定义的View对象,也可以用layoutinflat xml文件的方法
            CustomerView view = viewList[position];
ViewGroup viewpager = ((ViewGroup) container);
if(view == null) {
view = new CustomerView (mContext);
viewList[position] = view;
(viewpager).addView(view, 0);
}
return view;
}
@Override
public void destroyItem(View container, int position,
Object object) {
container.removeView(viewList[position]);
                   }

参考:http://rincliu.com/blog/2013/09/29/viewpager/


http://chatgpt.dhexx.cn/article/q18oH11n.shtml

相关文章

GridView1_PageIndexChanging 分页

//这里点击页面会报错所以要写这个 然后从新刷新一下 可以调一下属性什么的 this.GridView1.PageIndex e.NewPageIndex;jiazai(); c#后台写弹窗 跳转 Response.Write("<script>alert(修改成功);window.location.hrefhttp://localhost:65390/%E6%88%BF%E5%B1…

ViewPager控件之PagerAdapter适配器

一、ViewPager的基本用法 1、简介 ViewPager可以实现多个界面的左右滑动。ViewPager最典型的应用场景主要包 括引导页导航&#xff0c;轮转广告和页面菜单。 ViewPager最早出自4.0版本,为了兼容低版本安卓设备&#xff0c;谷歌官方给我们提供了 一个的软件包android.support.v4…

ViewPager onPageChangeListener总结

android ViewPager滑动事件讲解 今天在做项目的时候&#xff0c;由于要处理viewPager页面滑动的事件&#xff0c;所以对其进行了一个小小的研究&#xff1a; 首先ViewPager在处理滑动事件的时候要用到OnPageChangeListener OnPageChangeListener这个接口需要实现三个方法&am…

ViewPager onPageChangeListener总结

android ViewPager滑动事件讲解 今天在做项目的时候&#xff0c;由于要处理viewPager页面滑动的事件&#xff0c;所以对其进行了一个小小的研究&#xff1a; 首先ViewPager在处理滑动事件的时候要用到OnPageChangeListener OnPageChangeListener这个接口需要实现三个方法&#…

iscsi命令

iscsi客户端命令 iscsiadm 1.发现target设备 iscsiadm -m discovery -t sendtargets -p 10.12.22.61 疑问&#xff1a;10.12.22.60&#xff1a;3260&#xff0c;1 1表示什么意思(表示portal group tag,参考补充资料1)&#xff0c;此外&#xff0c;为什么连同ip为60的信息…

iSCSI 协议

iSCSI 协议 iSCSI协议结构 如同任何一个协议一样&#xff0c;iSCSI也有一个清晰的层次结构&#xff0c;根据OSI模型&#xff0c;iSCSI的协议栈自顶向下一共可以分为五层&#xff0c;如图所示&#xff1a; SCSI层&#xff1a;根据应用发出的请求建立SCSI CDB(命令描述块)&…

Linux与ISCSI

ISCSI&#xff08;Internet Small Computer System Interface&#xff09;:Internet 小型计算机系统接口&#xff0c;是一个基于 TCP/IP 的协 议&#xff0c;主要用于通过 IP 网络仿真 SCSI&#xff0c;从而为远程块存储设备提供数据传输和管理。说白了&#xff0c;就是通过 网…

ISCSI服务

Internet Small Computer System Interface:Internet 小型计算机系统接口&#xff0c;是一个基于 TCP/IP 的协 议&#xff0c;主要用于通过 IP 网络仿真 SCSI&#xff0c;从而为远程块存储设备提供数据传输和管理。说白了&#xff0c;就是通过 网络由专门的服务器提供存储管理&…

iSCSI 网络磁盘共享

17.1 iSCSI技术介绍 iSCSI技术实现了物理硬盘设备与TCP/TP网络传输协议的相互结合&#xff0c;使得用户可以通过互联网方便的获取到远程机房提供的共享存储资源 硬盘是计算机硬件设备中重要的组成部分之一&#xff0c;存储设备的IO读写速度快慢也直接影响着服务器整体性能的高…

ISCSI的部署与安装

iSCSI&#xff08;Internet Small Computer System Interface&#xff0c;Internet小型计算机系统接口&#xff09;是一种由IBM公司研究开发的IP SAN技术。 该技术是将现有SCSI接口与以太网络(Ethernet)技术结合&#xff0c;基于 TCP/IP的协议连接iSCSI服务端&#xff08;Targe…

SCSI协议与iSCSI协议

文章目录 1.SCSI协议2.iSCSI协议3.IO--SCSI错误处理机制 1.SCSI协议 SCSI的起源 SCSI出现的原因主要是因为原来的IDE接口的硬盘转速太慢&#xff0c;传输速率太低&#xff0c;因此高速的SCSI硬盘出现。其实SCSI并不是专为硬盘设计的&#xff0c;实际上它是一种总线型接口。由…

ISCSI详解(三)——ISCSI原理和架构

今天继续给大家介绍Linux运维相关知识&#xff0c;本文主要内容是ISCSI基础知识。 一、ISCSI架构 ISCSI的架构主要有以下两种&#xff1a; 1、控制器架构 在控制器架构下&#xff0c;ISCSI使用专门的数据传输芯片&#xff0c;专门的RAID数据校验芯片、高性能的cache缓存以及专…

iscsi服务器搭建

iscsi搭建 ISCSI服务介绍服务器配置&#xff08;IP:192.168.155.28&#xff09;客户端配置Linux&#xff08;IP:192.168.155.30&#xff09;Windows配置&#xff08;192.168.155.200&#xff09; ISCSI服务介绍 全称&#xff1a;Internet Small Computer System Interface——…

Windows iSCSI

iSCSI 题目一、安装iSCSI并创建存储位置二、配置iSCSI三、DC1连接iSCSI四、创建盘提示:若需要问题欢迎私聊‘ 题目 iSCSI 磁盘存储在D:\ISCSIDATA 中; iSCSI 磁盘提供给DC1 使用,磁盘容量500 G,启用chap 验证; DC1 上连接成功后,把磁盘格式化为NTFS 格式并挂载到卷标D …

【基于CentOS 7 的iscsi服务】

目录 一、概述 1.简述 2.作用 3. iscsi 4.相关名称 二、使用步骤 - 构建iscsi服务 1.使用targetcli工具进入到iscsi服务器端管理界面 2.实现步骤 2.1 服务器端 2.2 客户端 2.2.1 安装软件 2.2.2 在认证文件中生成iqn编号 2.2.3 开启客户端服务 2.2.4 查找可用的i…

ISCSI服务器搭建与配置

ISCSI服务简介 ISCSI简介&#xff1a; iSCSI( Internet Small Computer System Interface 互联网小型计算机系统接口) 技术是一种新存储技术&#xff0c;该技术是将现有的SCSI接口与以太网技术相结合&#xff0c;使服务器可与使用IP网络的存储装置互相交换资料。 iscsi 结构…

SCSI/ISCSI协议

SCSI即小型计算机接口&#xff08;Small Computer System Interface&#xff09;&#xff0c;指的是一个庞大协议体系&#xff0c;到目前为止经历了SCSI-1/SCSI-2/SCSI-3变迁。 SCSI协议定义了一套不同设备&#xff08;磁盘&#xff0c;磁带&#xff0c;处理器&#xff0c;光设…

iSCSI协议简介

本文综合了几篇参考文献的内容&#xff0c;做了删减与重组&#xff0c;但严格来说&#xff0c;不算原创。 笔者笔记如下&#xff1a; iSCSI initiator和target的核心功能都在内核中&#xff0c;无须人工干预&#xff1b;而要人工干预的大约是这么几件事&#xff1a; 1. 建立…

【存储】SCSI、iSCSI协议详解及对比

作 者&#xff1a; NGDCN 原文链接&#xff1a;【存储】SCSI、iSCSI协议详解及对比 - NGDCN 版 权&#xff1a; 本文由 NGDCN 于2022-11-11原创发布在 NGDCN&#xff0c;未经许可&#xff0c;禁止转载。 SCSI SCSI是小型计算机系统接口&#xff08;Small Compu…

ISCSI详解(二)——ISCSI基础知识

今天继续给大家介绍Linux运维相关知识&#xff0c;本文主要内容是ISCSI基础知识。 一、ISCSI简介 ISCSI&#xff0c;即Internel Small Computer System Interface&#xff0c;互联网小型计算机接口&#xff0c;就是在互联网上运行SCSI协议的一种技术。 ISCSI把原本用于用于计…