观心静

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  422 随笔 :: 0 文章 :: 86 评论 :: 139万 阅读

问题描述: 

  在使用ViewPager的适配器删除适配器里一个Item后依然会,而删除的这个item依然会保留缓存,适配器不会重新加载更新数据.如下代码:

复制代码
public class TReleaseCircleZoomablePagerAdapter extends PagerAdapter {
    private List<TReleaseCircleBase.Pic> mImageUrlList = new ArrayList<>();


    public void removeItem(int position){
        mImageUrlList.remove(position);
        notifyDataSetChanged();

    }

//....略
复制代码

在这个代码里removeItem(int position)是希望清理适配器List里的一项item,并且重新刷新.但是其实真实情况是并不会重新刷新...... 在滑动超过3个页面后才会让你那个删除item消失.

解决办法:

依然在这个适配器里重写public int getItemPosition(@NonNull Object object)方法

复制代码
public class TReleaseCircleZoomablePagerAdapter extends PagerAdapter {
    private List<TReleaseCircleBase.Pic> mImageUrlList = new ArrayList<>();

    public void removeItem(int position){
        mImageUrlList.remove(position);
        notifyDataSetChanged();

    }


    @Override
    public int getItemPosition(@NonNull Object object) {
//        return super.getItemPosition(object);
        return POSITION_NONE;
    }

//略......
复制代码

注意关键点是返回 POSITION_NONE

为什么呢?

  为什么我改了这个之后就可以在删除item后更新view了呢?好奇心害死猫,我们进一步探究一下.

  首先我们看看 return super.getItemPosition(object); 父类里写的返回值到底里面有啥

  

复制代码
    /**
     * 在主视图尝试确定项目的位置时调用
     * 已经改变。 如果给定的位置,则返回{@link #POSITION_UNCHANGED}
     * 如果适配器中不再存在该项,则item未更改或{@link #POSITION_NONE}。
     *
     * <p>The default implementation assumes that items will never
     * change position and always returns {@link #POSITION_UNCHANGED}.
     *
     * @param object Object representing an item, previously returned by a call to
     *               {@link #instantiateItem(View, int)}.
     * @return object's new position index from [0, {@link #getCount()}),
     *         {@link #POSITION_UNCHANGED} if the object's position has not changed,
     *         or {@link #POSITION_NONE} if the item is no longer present.
     */
    public int getItemPosition(@NonNull Object object) {
        return POSITION_UNCHANGED;
    }
复制代码

 

很好上面的意思是

如果视图item已经是加载过的,就使用 POSITION_UNCHANGED 来标识,表示这个item不需要重复更新

如果item在适配器里不存在,就说item未加载过,就使用 POSITION_NONE 来标识,标识这个item需要更新一次

接着继续探究下ViewPager是怎么调用getItemPosition()的

 

 

复制代码
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 (newPos == PagerAdapter.POSITION_UNCHANGED)if (newPos == PagerAdapter.POSITION_NONE) 就已经破案了...,只能说google真会写方法名称...

 

posted on   观心静  阅读(2853)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示