记录ListView的item中含有EditText控件时出现的问题

 之前在开发过程中,遇到过这样一个需求:在一个列表中,每一项里面有标题文字,有一个下拉框可以选选项,还有一个输入框,用户可以输入数字。刚开始一看感觉很简单,在android中列表用ListView控件,标题用TextView控件,下拉框用Spinner控件,输入框用EditView控件,没有什么特别的,ok开搞。写完后一运行测试,出现问题了:当选取完下拉框中的某一项后,再点击输入框输入数字后,发现下拉框被还原了,变成了未选择时的默认状态,这是怎么回事?

 为了找到问题出现的原因,我反复进行测试,发现在输入框输入内容后不仅影响到该item中的下拉框,还会影响到其他item的下拉框。这样看来的话那应该就是ListView的复用机制造成的了,也就是适配器中的getView方法。getView方法的作用就是刷新它所在的ListView的,其方法体中就是给控件赋值的语句。ListView有很多个item,但是不可能给每个item都分配一块内存来创建视图,如果给每一个item都创建一个视图的话,ListView如果有成千上万个item,那就需要非常大的内存空间了,这显然是不可能的。所以ListView用的是复用机制,或者说缓存机制。有个叫做Recycler的构件,用来存储不在屏幕范围内的item。向下滑动ListView时,如果item完全滚出屏幕范围,就将这个item放在Recycler中,当后面的item需要滚入屏幕的时候,系统会查看Recycler中是否有可以复用的item,如果有,就把这个item拿出来用,然后调用getView方法把数据重新赋值,这样就不需要为每一个item都创建一个视图。这个getView方法会在ListView滚动时,屏幕外的item即将滚入屏幕中时调用,每有一个item滚入屏幕,getView方法就会调用一次。还有就是程序刚创建ListView的时候,item从无到有的时候会调用,屏幕中能显示几个item(包括显示不全的),就会调用几次。换言之,也就是说当item的可见性发生变化时,会调用getView方法。

 为了验证自己的猜想,我在getView方法中写下了一条打印日志语句,然后运行程序进行操作,果然打印出了两批日志,一批是ListView刚创建时调用的getView,另一批就是我进行操作时调用的,说明的确是这里的原因。但是我没有滚动ListView,也不是ListView刚创建时调用的,为什么会再次调用getView方法呢?我又详细的进行了观察,发现问题并不是在输入框中输入内容导致的,而是在点击输入框,软键盘弹出的一瞬间,已经选择完毕的下拉框被还原了,说明问题可能是软键盘导致的,于是我又试了下先不选择下拉框,先点击输入框让软键盘弹出,然后选择下拉框中的某一项,最后把软件盘收起来,下拉框果然又被还原了。我觉得这可能是焦点的原因,软件盘未弹出时焦点在整个屏幕,也就是ListView,软键盘弹出时会获得焦点,焦点到了软键盘(或者说EditTtext),收起时又会失去焦点,焦点又回到ListView,而ListView刚创建的时候ListView也会获得焦点,所以我猜想可能是系统把软键盘弹出和收起时的焦点变化当作了ListView创建时的焦点变化,以为ListView是刚创建,所以调用了getView方法。这个猜想是否正确还有待研究。

 我自己想了一些方案来解决这个问题,概括来说就是创建一个Map来记录每个item的position(即下标)和item中下拉框的选择情况,每当调用getView方法时,就把Map中存储的当前item的position对应的下拉框选择情况设置到当前item中的下拉框上,来达到解决问题的目的。虽然能解决问题但是这样效果并不是很好,而且会对程序性能有一定影响。我也上网查了资料,普遍也都是类似的解决思路。后来我突发奇想把ListView换成RecyclerView试了一下,惊喜的发现用RecyclerView竟然没有这个问题。RecyclerView作用和listiview类似,可以说是增强版的ListView。这样问题就解决了,不过为什么RecyclerView不存在这个问题,以后还待研究。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值