当前位置: 首页 > java >正文

ViewPager FragmentPagerAdapter在系统杀死应用后重建时UI不刷新的问题

解决方案

通过重写getItemId方法,返回Fragment的hashCode

@Override
public long getItemId(int position) {/*** 恢复状态重建时,新的 Fragment 不刷新UI。* 原因:instantiateItem 中通过 mFragmentManager.findFragmentByTag(name) 无法找到新的 Fragment,* 因为 name 是由 container.getId() +  getItemId 组成(其中getItemId默认返回position),二者都没变化* 为了让mFragmentManager正确找到新Fragment,那就让 getItemId(即name) 与 Fragment 绑定,而不仅与position绑定* 这样上述问题得解*/return fragmentList.get(position).hashCode();
}
原理解析
一、默认机制的问题根源

FragmentPagerAdapter中,instantiateItem方法会使用makeFragmentName生成Fragment的唯一标识Tag,组合规则如下:

"android:switcher:" + viewId + ":" + getItemId(position)
  • 默认行为:父类的getItemId()直接返回position。当Activity重建时,相同位置的新旧Fragment生成相同的Tag,导致系统优先从FragmentManager缓存中复用旧实例,而不会调用getItem()创建新Fragment。
二、解决方案的核心逻辑

通过重写getItemId(),使其返回值与Fragment对象本身相关联:

@Override
public long getItemId(int position) {return fragmentList.get(position).hashCode();
}

实现效果

  1. 唯一Tag生成:即使position相同,只要Fragment对象不同,hashCode必然不同,新旧Fragment的Tag不同;
  2. 阻断缓存复用:系统通过findFragmentByTag查找失败,强制调用getItem()创建新Fragment实例;
  3. 数据一致性保证:新Fragment从最新数据源初始化,避免恢复旧状态导致的UI错乱。
三、源码级验证

查看FragmentPagerAdapter.instantiateItem()的关键逻辑:

// 生成唯一标识Tag
final long itemId = getItemId(position);
String name = makeFragmentName(container.getId(), itemId);// 优先从缓存中查找Fragment
Fragment fragment = mFragmentManager.findFragmentByTag(name);
if (fragment != null) {mCurTransaction.attach(fragment); // 命中缓存,直接复用旧实例
} else {fragment = getItem(position);       // 未命中,创建新实例mCurTransaction.add(..., name);
}

在这里插入图片描述
在这里插入图片描述

四、示例代码
public class ServerPagerAdapter extends FragmentPagerAdapter {private final List<ServerFragment> fragmentList;@Overridepublic long getItemId(int position) {return fragmentList.get(position).hashCode(); // 绑定对象哈希值}// 其他代码保持默认实现即可
}

总结

通过重写getItemId改变Fragment的Tag生成规则,从根本上阻断了系统对旧Fragment实例的复用机制。此方案以最小代码改动实现了数据与UI的强一致性,适用于动态数据场景的ViewPager适配。但需注意:长期持有大量Fragment对象可能引发内存压力,建议结合FragmentStatePagerAdapter使用以优化资源回收。

http://www.xdnf.cn/news/1904.html

相关文章:

  • Hadoop生态圈框架部署 - Windows上部署Hadoop
  • MySQL锁
  • redis客户端库redis++在嵌入式Linux下的交叉编译及使用
  • 从线性到非线性:简单聊聊神经网络的常见三大激活函数
  • 不吃【Numpy】版
  • Spring AI 快速入门:从环境搭建到核心组件集成
  • 高精度运算
  • 有关虚拟奢侈品
  • Java知识日常巩固(四)
  • Linux Ubuntu18.04下安装Qt Craeator 5.12.9(图文详解)
  • 【Qt】文件
  • 探秘LLM推理模型:hidden states中藏着的self verification的“钥匙”
  • PubMed PDF下载 cloudpmc-viewer-pow逆向
  • C#中实现XML解析器
  • YOLOX-PAI手部检测模型
  • RocketMQ 主题与队列的协同作用解析(既然队列存储在不同的集群中,那要主题有什么用呢?)---管理命令、配置安装
  • 二项分布详解:从基础到应用
  • Nginx---总结
  • 服务网格助力云原生后端系统升级:原理、实践与案例剖析
  • 第25周:DenseNet+SE-Net实战
  • 跟我学C++中级篇——处理对象的复制
  • Java实现加密(七)国密SM2算法的签名和验签(附商用密码检测相关国家标准/国密标准下载)
  • 深度解析 Java 排序中的 Null 值处理:Comparator.nullsLast 与 Comparator.nullsFirst 最佳实践
  • 酷狗音乐安卓版K歌功能与音效优化体验测评
  • 整合 CountVectorizer 和 TfidfVectorizer 绘制词云图
  • easyExcel导入导出convert
  • 算法训练营 Day1
  • 课程9. 机器翻译,Seq2Seq与Attention
  • BS客户端的单点登录
  • 贪心算法~~