Android-FragmentPagerAdapter刷新无效的解决方案
发布日期:2021-06-24 18:19:31 浏览次数:3 分类:技术文章

本文共 7208 字,大约阅读时间需要 24 分钟。

按照通常使用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
mFragmentList; 11 private FragmentManager mFragmentManager; 12 /**下面两个值用来保存Fragment的位置信息,用以判断该位置是否需要更新*/ 13 private SparseArray
mFragmentPositionMap; 14 private SparseArray
mFragmentPositionMapAfterUpdate; 15 16 public BaseFragmentPagerAdapter(FragmentManager fm, List
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 * 保存更新之前的位置信息,用
的键值对结构来保存 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 * 保存更新之后的位置信息,用
的键值对结构来保存 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 新Fragment100 */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 * 移除指定的Fragment110 * @param fragment 目标Fragment111 */112 public void removeFragment(BaseFragment fragment) {113 //先从List中移除114 mFragmentList.remove(fragment);115 //然后从Transaction移除116 removeFragmentInternal(fragment);117 //最后刷新Adapter118 notifyItemChanged();119 }120 121 /**122 * 移除指定位置的Fragment,同 { @link #removeFragment(BaseFragment fragment)}123 * @param position124 */125 public void removeFragment(int position) {126 BaseFragment fragment = mFragmentList.get(position);127 //然后从List中移除128 mFragmentList.remove(fragment);129 //先从Transaction移除130 removeFragmentInternal(fragment);131 //最后刷新Adapter132 notifyItemChanged();133 }134 135 /**136 * 添加Fragment137 * @param fragment 目标Fragment138 */139 public void addFragment(BaseFragment fragment) {140 mFragmentList.add(fragment);141 notifyItemChanged();142 }143 144 /**145 * 在指定位置插入一个Fragment146 * @param position 插入位置147 * @param fragment 目标Fragment148 */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移除Fragment163 * @param fragment 目标Fragment164 */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 @Override175 public long getItemId(int position) {176 // 获取当前数据的hashCode,其实这里不用hashCode用自定义的可以关联当前Item对象的唯一值也可以,只要不是直接返回position177 return mFragmentList.get(position).hashCode();178 }179 180 @Override181 public Fragment getItem(int position) {182 return mFragmentList.get(position);183 }184 185 @Override186 public int getCount() {187 return mFragmentList.size();188 }189 190 public List
getFragments() {191 return mFragmentList;192 }193 }

测试代码:

1 public class TestActivity extends FragmentActivity implements View.OnClickListener { 2     List
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 @Override29 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/weixin_34248258/article/details/86399956 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Docker,Docker Compose,Docker Swarm,Kubernetes之间的区别
下一篇:java 正则表达式获得html字符串中<img src>中的src中的url地址

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2024年04月23日 05时52分58秒