listView和gridView中item复用的相关问题

listView和gridView的复杂处理中经常会因为item复用引起一些看似很奇怪的问题,我最近的一个项目中用到gridview图片上传和局部刷新,
如果图片只是像qq和微信说说一样最多9张图片也还好,但是我们伟大的产品设计的不同的上传页面的图片上限是不一样的,几个到几十个不等,
自测发现几个和item复用有关的bug,解决之后总结一下自己的心得,我下面的描述都是值gridview的情况,读者可自行脑补listview的类似情况:

GridView的数据适配器的getView中部分代码如下:

@Override
    public View getView(final int position, View convertView,
            ViewGroup parent) {
        final ViewHolder viewHolder;
        if (convertView == null) {
            LogUtils.i("---adapter-item复用测试----新创建----position=" + position);
            convertView = mInflater.inflate(R.layout.grid_choosed_item, null);
            viewHolder = new ViewHolder();
            。。。
            convertView.setTag(viewHolder);
        } else {
            LogUtils.i("---adapter-item复用测试----复用----position=" + position);
            viewHolder = (ViewHolder) convertView.getTag();
        }
        。。。
    }

程序设置说明和运行log如下:
(每屏可显示五行,gridview设置的是3列,所以一屏幕能显示15个item)
—adapter-item复用测试—-新创建—-position=0
—adapter-item复用测试—-新创建—-position=1
—adapter-item复用测试—-新创建—-position=2
—adapter-item复用测试—-新创建—-position=3
—adapter-item复用测试—-新创建—-position=4
—adapter-item复用测试—-新创建—-position=5
—adapter-item复用测试—-新创建—-position=6
—adapter-item复用测试—-新创建—-position=7
—adapter-item复用测试—-新创建—-position=8
—adapter-item复用测试—-新创建—-position=9
—adapter-item复用测试—-新创建—-position=10
—adapter-item复用测试—-新创建—-position=11
—adapter-item复用测试—-新创建—-position=12
—adapter-item复用测试—-新创建—-position=13
—adapter-item复用测试—-新创建—-position=14
(向上滑动,第二屏的第一行是新创建的,因为第二屏的第一行划入屏幕的过程中的时候第一屏的第一行还没有完全消失,所以这时候内存中并没有空闲的contentView对象)
—adapter-item复用测试—-新创建—-position=15
—adapter-item复用测试—-新创建—-position=16
—adapter-item复用测试—-新创建—-position=17
(从这以后不管是向上还是向下滑动都会复用,因为现在内存中一共有18个contentView对象,而一屏只能显示15个,不管从上还是从下划入的item都可以复用内存中多余的三个contentView对象)
—adapter-item复用测试—-复用—-position=18
—adapter-item复用测试—-复用—-position=19
—adapter-item复用测试—-复用—-position=20
—adapter-item复用测试—-复用—-position=21
—adapter-item复用测试—-复用—-position=22
—adapter-item复用测试—-复用—-position=23
(到底之后向下滑动,上面三行全部是复用的)
—adapter-item复用测试—-复用—-position=6
—adapter-item复用测试—-复用—-position=7
—adapter-item复用测试—-复用—-position=8
—adapter-item复用测试—-复用—-position=3
—adapter-item复用测试—-复用—-position=4
—adapter-item复用测试—-复用—-position=5
—adapter-item复用测试—-复用—-position=0
—adapter-item复用测试—-复用—-position=1
—adapter-item复用测试—-复用—-position=2

item复用规律总结:
列表第一页肯定都是新创建的,不需要解释;
向上滑动,第二页的第一个item也是新创建的,因为它显示出来的时候第一页还没有item完全隐藏,所以没有contentView可供复用;
继续向上或者向下滑动,之后所有的item都是复用的。
(注意:网上很多帖子的说法是,屏幕能显示n个item的话,内存中就一直存在n个item。但我的实验结果并不是这样,我觉得这种说法是错误的。如有不对,欢迎指正!)

我还想在这里补充另外一个问题,就是局部刷新时候我们通常会通过viewItem = gridview.getChildAt()这个方法获取
目标item的布局,第一屏的时候没有问题,但是到第二屏的第二行item之后就开始出现获取结果为null的情况:
我这里需要说明的是getChildAt(position)方法是获取当前屏幕可见的item中第几个item的布局,所以使用时候需要这样写:
viewItem = gridview.getChildAt(position - gridview.getFirstVisiblePosition())才能保证都能正确获取到结果。
这个方法对于我们使用来说,和item复用没有关系,我们只需要保证我们获取的是屏幕上所显示的第一个item就行了,
至于该方法内部的实现原理,肯定是先判断当前item是否复用contentView,如果复用就去找到它锁复用的item对应的contentView,再返回该布局。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值