解决:特殊应用场景下--Android 在list view 中使用switch 遇到的switch 重置的问题

首先说一下应用场景和问题:

项目需要加载一个listview,每个list item中有一个switch 按钮。list item中的switch 在初始化时,需要根据数据对应的boolean 值来设置switch的开关状态。我调用的是setChecked()来设置状态。switch 的开关侦听函数 为修改一个之前初始化的boolean值。

这样遇到了一个问题,就是当设置为On的switch在滑出界面的时候,再将其滑入屏幕,switch有可能自动就变为关,我查看那个依据的boolean值,也被改了。

我明明没有点击按钮,为什么switch自己就换过去了???


发现问题:

百思不得其解之后,我在工程中寻找修改那个Boolean值得代码,只有在switch的监听函数中才发现有!

只能 在修改Boolean 值处加上主动throw Exception,并try catch代码  的方式获取前前后后的调用栈。

解决:特殊应用场景下--Android 在list view 中使用switch 遇到的switch 重置的问题_第1张图片

运行之后,重现错误,发现结果如下

解决:特殊应用场景下--Android 在list view 中使用switch 遇到的switch 重置的问题_第2张图片

2 处的代码就是setChecked(boolean ...)

发现调用

	onCheckedChanged的
是初始化的setChecked()

我们知道,当list item 滑出屏幕时就意味着有新的list item 滑进屏幕,新的list item 调用getview  获取的是滑出屏幕的item 的convertView。

所以绘制新的item ,调用setChecked(), 实际调用的是旧的对象的setChecked.

通过阅读setChecked源码,

switch:

解决:特殊应用场景下--Android 在list view 中使用switch 遇到的switch 重置的问题_第3张图片
父类:CompundButton


解决:特殊应用场景下--Android 在list view 中使用switch 遇到的switch 重置的问题_第4张图片


由于旧的convertView的OncheckChangeListener 依然存在,所以setChecked就触发了onCheckedChange函数,由于新的list item 对应的Boolean 值很可能是false,这样就触发了onCheckedListener(false)。造成把滑出屏幕的item 的Boolean改成了false. 自然再滑进的时候就变成关了


 解决方式



要切断setChecked 初始化 和调用onCheckedChanged 之间的联系,只需要在setChecked()之前将listenter 设置为空即可


解决:特殊应用场景下--Android 在list view 中使用switch 遇到的switch 重置的问题_第5张图片


最后解决了这个问题


总结一下

遇到奇怪的问题的时候,

在可疑的地方主动抛出异常获取调用栈,以及 阅读源码发现bug原因和bug解决办法是 解决bug的有效的途径。



你可能感兴趣的:(Android)