Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 803|回复: 0

FragmentStatePagerAdapter.notifyDataSetChanged不刷新页面的解决的方法

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-5-2 15:50:33 | 显示全部楼层 |阅读模式

    公司做医疗产品的,显示操作用的是android。所以我就用上下两个部分大致是固定的,仅仅有中间会有6个页面的切换,当中会有两个用户的切换。即普通用户和管理员用户,图片能够大致展示一下

    其他页面是同样的,就这两个页面不一样,以下的是管理员用户,一想到其他页面一样的,中间就用了一个ViewPager,然后为了缓存多个页面。用到了FragmentStatePagerAdapter,然后通过setOffscreenPageLimit(6)最多缓存了6个页面,这样一下,就不用操心每一个页面的fragment的声明周期对我项目的影响了。这个界面可能没有。可是其他界面的检測什么的,线程和Ui比較复杂。easy受fragment声明周期影响而crash。

    可是这个里有个奇怪的要求,管理员用户的项目设置界面的功能居然不是全的,有两个在普通用户那边。这个设计我也非常纳闷,只是,还是得做啊,之后。就遇到了题目所说的问题,notifyDataSetChanged尽管会有页面的增多和降低,可是。项目界面就是不刷新。

    然后找了度娘和谷哥,出来的答案大多指向同一篇文章http://www.cnblogs.com/dancefire/archive/2013/01/02/why-notifyDataSetChanged-does-not-work.html,稍微看了一遍,照着上面方法试了。报错。依然不得其要领,然后自己去看了下源代码,攻克了。分享并记住这个问题,免得以后再犯错

    先进入notifyDataSetChanged

    发现这句,mObservable,看名字,观察者,应该就是用来实时监測viewPager绑定数据源的变化的。再进入notifychanged方法

    发现一个遍历。这个遍历会去调用mObservers中的每个元素的变化。我们再进入onChanged,

    到了,这里,发现onChanged仅仅是一个抽象类中的方法。,既然会调用,肯定会被重写咯,找了一圈。在viewPager中的内部内继承了。


    躲的还是蛮深的,只是这还没有找到我们须要关注的地方,那就继续找,dataSetChanged

    void dataSetChanged() {
            // This method only gets called if our observer is attached, so mAdapter is non-null.
    
            final int adapterCount = mAdapter.getCount();
            mExpectedAdapterCount = adapterCount;
            boolean needPopulate = mItems.size() < mOffscreenPageLimit * 2 + 1 &&
                    mItems.size() < adapterCount;
            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);
    
                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, adapterCount - 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();
            }
        }
    这里就是我们须要关注的地方了,一看这么多。确实有点头疼。只是,我们仅仅关注重点,看第13行,有句
    final int newPos = mAdapter.getItemPosition(ii.object);

    这里就调用的了我们的adapter中的getItemPosition,我们再看看getItemPosition会返回什么,会接收什么,复写fragmentStatePagerAdapter中的getItemPosition方法,发现仅仅会返回父类中的方法

    接着看父类中的方法

    再看看POSITION_UNCHANGED是干嘛用的。


    马丹,这下总算是明确了,这里一直return POSITION_UNCHANGED;

    return一个“未改变”的标志给dataSetChanged()中,它当然打死都不更新咯。请看dataSetChanged()中的第15-17行


    魂淡,居然知道原因了。那就好做了。直接将要刷新的页面 return POSITION_NONE

    @Override
        public int getItemPosition(Object object) {
            if (object.getClass().getName().equals(ProjectFragment.class.getName())
                    || object.getClass().getName().equals(ProjectFragment2.class.getName())) {
                return POSITION_NONE;
            }
            return super.getItemPosition(object);
        }


    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-1-12 08:46 , Processed in 0.062555 second(s), 27 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表