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入门到精通教程
查看: 470|回复: 0

Android-FragmentPagerAdapter刷新无效的解决方案

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-6 11:05
  • 签到天数: 748 天

    [LV.9]以坛为家II

    2034

    主题

    2092

    帖子

    70万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    705612
    发表于 2021-5-16 13:45:23 | 显示全部楼层 |阅读模式

    按照通常使用ListView的习惯做法,如果你只是更新保存Fragment的List数据,然后调用adapter的notifyDataSetChanged()是不会起作用的.

    搜索了下发现此问题普遍存在,多数是说先移除Fragment再notifyDataSetChanged(),因为FragmentPagerAdapter内部会缓存Fragment,但是经测试发现仅仅这样干是不行的。

    这可能是Android一个BUG, 与此问题相关的主要有两个方法:

    • getItemPosition()
    • instantiateItem()

    具体的分析内容参见原文,那么重写后的adapter如下:

      1 /**
      2  * 加载显示Fragment的ViewPagerAdapter基类
      3  * 提供可以刷新的方法
      4  *
      5  * @author Fly
      6  * @e-mail 1285760616@qq.com
      7  * @time 2018/3/22
      8  */
      9 public class BaseFragmentPagerAdapter extends FragmentPagerAdapter {
     10     private List<BaseFragment> mFragmentList;
     11     private FragmentManager mFragmentManager;
     12     /**下面两个值用来保存Fragment的位置信息,用以判断该位置是否需要更新*/
     13     private SparseArray<String> mFragmentPositionMap;
     14     private SparseArray<String> mFragmentPositionMapAfterUpdate;
     15 
     16     public BaseFragmentPagerAdapter(FragmentManager fm, List<BaseFragment> fragments) {
     17         super(fm);
     18         mFragmentList = fragments;
     19         mFragmentManager = fm;
     20         mFragmentList = fragments;
     21         mFragmentPositionMap = new SparseArray<>();
     22         mFragmentPositionMapAfterUpdate = new SparseArray<>();
     23         setFragmentPositionMap();
     24         setFragmentPositionMapForUpdate();
     25     }
     26 
     27     /**
     28      * 保存更新之前的位置信息,用<hashCode, position>的键值对结构来保存
     29      */
     30     private void setFragmentPositionMap() {
     31         mFragmentPositionMap.clear();
     32         for (int i = 0; i < mFragmentList.size(); i++) {
     33             mFragmentPositionMap.put(Long.valueOf(getItemId(i)).intValue(), String.valueOf(i));
     34         }
     35     }
     36 
     37     /**
     38      * 保存更新之后的位置信息,用<hashCode, position>的键值对结构来保存
     39      */
     40     private void setFragmentPositionMapForUpdate() {
     41         mFragmentPositionMapAfterUpdate.clear();
     42         for (int i = 0; i < mFragmentList.size(); i++) {
     43             mFragmentPositionMapAfterUpdate.put(Long.valueOf(getItemId(i)).intValue(),  String.valueOf(i));
     44         }
     45     }
     46 
     47    /**
     48     * 在此方法中找到需要更新的位置返回POSITION_NONE,否则返回POSITION_UNCHANGED即可
     49     */
     50     @Override
     51     public int getItemPosition(Object object) {
     52         int hashCode = object.hashCode();
     53         //查找object在更新后的列表中的位置
     54         String position = mFragmentPositionMapAfterUpdate.get(hashCode);
     55         //更新后的列表中不存在该object的位置了
     56         if (position == null) {
     57             return POSITION_NONE;
     58         } else {
     59             //如果更新后的列表中存在该object的位置, 查找该object之前的位置并判断位置是否发生了变化
     60             int size = mFragmentPositionMap.size();
     61             for (int i = 0; i < size ; i++) {
     62                 int key = mFragmentPositionMap.keyAt(i);
     63                 if (key == hashCode) {
     64                     String index = mFragmentPositionMap.get(key);
     65                     if (position.equals(index)) {
     66                         //位置没变依然返回POSITION_UNCHANGED
     67                         return POSITION_UNCHANGED;
     68                     } else {
     69                         //位置变了
     70                         return POSITION_NONE;
     71                     }
     72                 }
     73             }
     74         }
     75         return POSITION_UNCHANGED;
     76     }
     77 
     78     /**
     79      * 将指定的Fragment替换/更新为新的Fragment
     80      * @param oldFragment 旧Fragment
     81      * @param newFragment 新Fragment
     82      */
     83     public void replaceFragment(BaseFragment oldFragment, BaseFragment newFragment) {
     84         int position = mFragmentList.indexOf(oldFragment);
     85         if (position == -1) {
     86             return;
     87         }
     88         //从Transaction移除旧的Fragment
     89         removeFragmentInternal(oldFragment);
     90         //替换List中对应的Fragment
     91         mFragmentList.set(position, newFragment);
     92         //刷新Adapter
     93         notifyItemChanged();
     94     }
     95 
     96     /**
     97      * 将指定位置的Fragment替换/更新为新的Fragment,同{@link #replaceFragment(BaseFragment oldFragment, BaseFragment newFragment)}
     98      * @param position    旧Fragment的位置
     99      * @param newFragment 新Fragment
    100      */
    101     public void replaceFragment(int position, BaseFragment newFragment) {
    102         BaseFragment oldFragment = mFragmentList.get(position);
    103         removeFragmentInternal(oldFragment);
    104         mFragmentList.set(position, newFragment);
    105         notifyItemChanged();
    106     }
    107 
    108     /**
    109      * 移除指定的Fragment
    110      * @param fragment 目标Fragment
    111      */
    112     public void removeFragment(BaseFragment fragment) {
    113         //先从List中移除
    114         mFragmentList.remove(fragment);
    115         //然后从Transaction移除
    116         removeFragmentInternal(fragment);
    117         //最后刷新Adapter
    118         notifyItemChanged();
    119     }
    120 
    121     /**
    122      * 移除指定位置的Fragment,同 {@link #removeFragment(BaseFragment fragment)}
    123      * @param position
    124      */
    125     public void removeFragment(int position) {
    126         BaseFragment fragment = mFragmentList.get(position);
    127         //然后从List中移除
    128         mFragmentList.remove(fragment);
    129         //先从Transaction移除
    130         removeFragmentInternal(fragment);
    131         //最后刷新Adapter
    132         notifyItemChanged();
    133     }
    134 
    135     /**
    136      * 添加Fragment
    137      * @param fragment 目标Fragment
    138      */
    139     public void addFragment(BaseFragment fragment) {
    140         mFragmentList.add(fragment);
    141         notifyItemChanged();
    142     }
    143 
    144     /**
    145      * 在指定位置插入一个Fragment
    146      * @param position 插入位置
    147      * @param fragment 目标Fragment
    148      */
    149     public void insertFragment(int position, BaseFragment fragment) {
    150         mFragmentList.add(position, fragment);
    151         notifyItemChanged();
    152     }
    153 
    154     private void notifyItemChanged() {
    155         //刷新之前重新收集位置信息
    156         setFragmentPositionMapForUpdate();
    157         notifyDataSetChanged();
    158         setFragmentPositionMap();
    159     }
    160 
    161     /**
    162      * 从Transaction移除Fragment
    163      * @param fragment 目标Fragment
    164      */
    165     private void removeFragmentInternal(BaseFragment fragment) {
    166         FragmentTransaction transaction = mFragmentManager.beginTransaction();
    167         transaction.remove(fragment);
    168         transaction.commitNow();
    169     }
    170 
    171     /**
    172      * 此方法不用position做返回值即可破解fragment tag异常的错误
    173      */
    174     @Override
    175     public long getItemId(int position) {
    176         // 获取当前数据的hashCode,其实这里不用hashCode用自定义的可以关联当前Item对象的唯一值也可以,只要不是直接返回position
    177         return mFragmentList.get(position).hashCode();
    178     }
    179 
    180     @Override
    181     public Fragment getItem(int position) {
    182         return mFragmentList.get(position);
    183     }
    184 
    185     @Override
    186     public int getCount() {
    187         return mFragmentList.size();
    188     }
    189 
    190     public List<BaseFragment> getFragments() {
    191         return mFragmentList;
    192     }
    193 }

    测试代码:

     1 public class TestActivity extends FragmentActivity implements View.OnClickListener {
     2     List<Fragment> mFragmentList;
     3     ViewPager mViewPager;
     4     public BaseFragmentPagerAdapter mAdapter;
     5 
     6     @Override
     7     protected void onCreate(Bundle savedInstanceState) {
     8         super.onCreate(savedInstanceState);
     9         setContentView(R.layout.activity_test);
    10         mViewPager = findViewById(R.id.vp);
    11         findViewById(R.id.btn_change).setOnClickListener(this);
    12 
    13         mFragmentList = new ArrayList<>();
    14         mFragmentList.add(getFg("AAA"));
    15         mFragmentList.add(getFg("BBB"));
    16         mFragmentList.add(getFg("CCC"));
    17         mFragmentList.add(getFg("DDD"));
    18         mAdapter = new BaseFragmentPagerAdapter(getSupportFragmentManager(), mFragmentList);
    19         mViewPager.setAdapter(mAdapter);
    20     }
    21 
    22     private TestFragment getFg(String a){
    23         TestFragment fragment = new TestFragment();
    24         fragment.setTest(a);
    25         return fragment;
    26     }
    27 
    28     @Override
    29     public void onClick(View view) {
    30         TestFragment eee = getFg("EEE");
    31 
    32         //新增
    33         mAdapter.addFragment(eee);
    34         //插入
    35         mAdapter.insertFragment(1, eee);
    36 
    37         //删除
    38         mAdapter.removeFragment(1);
    39         //删除
    40         mAdapter.removeFragment(mFragmentList.get(1));
    41 
    42         //替换
    43         mAdapter.replaceFragment(1, eee);
    44         //替换
    45         mAdapter.replaceFragment(mFragmentList.get(0), eee);
    46     }
    47 }

    内容取自

    https://blog.csdn.net/lyabc123456/article/details/79797552

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

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-5-19 12:43 , Processed in 0.062822 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

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