问题:当ListView选定的ListItem视图中存在一些UI组件,如CheckBox,希望保存状态,但实际上第一次完成时发现勾选后的选项在列表往下滑再滑回去后,状态没有保存

解决过程:

1)思考后想到这个原因是因为重用了convertView,当重用converView时,原先勾选的状态没有保存,又被新的数据源覆盖,重点代码为:

if (convertView == null) {
                convertView = getLayoutInflater().inflate(
                        R.layout.city_list_item, null);
            }
CheckBox selectedCheckBox = (CheckBox) convertView
                    .findViewById(R.id.isSelected);
CityItem data = cityItems.get(position);            //data是数据源
selectedCheckBox.setChecked(data.getSelected());
                                      //getSelected()意欲读取保存状态

视图重用

后来的做法是在数据源中添加一个isSelected变量,来记录选择值,并在checkBox上添加监听器,当勾选时触发保存事件:

 selectedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){

                 @Override
                 public void onCheckedChanged(CompoundButton buttonView,
                         boolean isChecked) {
                     // TODO Auto-generated method stub

                     CityItem c= cityItems.get(position);
                     c.setSelected(isChecked);
                     Log.i("change2","change2"+"  "+c.toString()+" "+isChecked);
                 }

             });

监听勾选状态改变事件

注意这里有个小细节,就是传入getView时将position变量设置为final,变成一个常量,绑定到监听事件中,当勾选状态改变时会引用原先绑定好的常量去设定,这样就对应到了实际的数据源;

2)再次运行时,发现还是有问题了,状态依旧没有保存,通过跑断点发现监听事件是有触发的,但是触发的场合并没有我们想象的那样完美,你会发现重写视图时该监听事件也是被捕捉到了,为什么呢?因为 "selectedCheckBox.setChecked(c.getSelected()); "这一方法也是改变了状态值,被监听器捕捉到了,理下思路我们也就能明白了:原先视图绑定了A数据源(为测试方便,将A数据展示放在了列表头),监听器里绑定了position,勾选绑定事件触发后,将值存入,然后滑动界面,之后A数据源不可见,被绑定的视图被B项重用,这时 “CityItem c = cityItems.get(position); ” 获得的是新的数据源B,但在这时我们执行了CheckBox的状态设置语句,此时监听事件就被触发了,但监听器中绑定的依旧是原先的position,悲剧就发生了,A数据源的状态被B数据源覆盖了;

这时问题就很明显了,因为监听器中绑定的position与监听到的状态改变不一定一致,导致错乱。

3)在阅读学习了日落城的博客 http://www.cnblogs.com/wujd/archive/2012/08/17/2635309.html 关于这方面的解析,找到了解决方案:那就是通过交换设置监听事件和重用对象后的设置状态语句;一开始一直想不明白,为什么可行?后来想了一阵子终于明白了,因为监听设置提前于状态设置语句,这样每次的监听都被保证绑定了的position与触发事件的项一致,哪怕后来状态设置时再次触发了状态改变事件也已经能保证是自身的数据源正确显示。

 @Override
 public View getView(final int position, View convertView,    ViewGroup parent) {
         if (convertView == null) {
             convertView = getLayoutInflater().inflate(
                         R.layout.city_list_item, null);
         }
         CityItem c = cityItems.get(position);
             CheckBox selectedCheckBox = (CheckBox) convertView
                     .findViewById(R.id.isSelected);
             selectedCheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){

                 @Override
                 public void onCheckedChanged(CompoundButton buttonView,
                         boolean isChecked) {
                     // TODO Auto-generated method stub

                     CityItem c= cityItems.get(position);
                     c.setSelected(isChecked);
                                     }

             });
             selectedCheckBox.setChecked(c.getSelected());
         return convertView;
 }

getView模块

最新文章

  1. 理清JavaScript正则表达式--上篇
  2. JPA 各种基本用法
  3. cannot find module 'xml2js'
  4. myeclipse中的文件内容被覆盖如何恢复
  5. spring 集成 Hibernate4.3.X org.hibernate.service.jta.platform.spi.JtaPlatform异常
  6. windows10 环境下theano安装
  7. HADOOP :: java.lang.ClassNotFoundException: WordCount
  8. HDU4272LianLianKan(dfs)
  9. Javascript之简单按钮搜索功能
  10. 动态用javascript来修改单选框性别
  11. pyqt中使用matplotlib绘制动态曲线 – pythonic
  12. index_ss hint 使用的运行计划变化对照
  13. python初始化MySQL数据库模板
  14. bootstrap 轮播模板
  15. 34.Ajax
  16. 使用Github pages+jekyll搭建自己的博客(windows版)
  17. 在线修改redo日志大小
  18. 数据库MySQL——初识
  19. Linux Centos 删除除某(多)个文件之外的所有文件
  20. SpriteKit 关于categoryBitMask collisionBitMask contactTestBitMask 遇到的一些问题

热门文章

  1. [ActionScript 3.0] AS3.0 火焰效果
  2. Zerojudge解题经验交流
  3. Mysql备份迁移——MySqlBackup(.net)——(无法解决视图嵌视图报错)
  4. 使用opencv设置图像的格式以及帧率
  5. MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作
  6. MSsql 服务器之间远程及其链接查询
  7. C#通过安全证书生成签名和验签辅助类
  8. 苹果刷机相关开源代码(如iRecovery等)收集汇总(不断更新中...)
  9. 关于HTML(JSP)页面的缓存设置 -- cache-control
  10. PIC32MZ tutorial -- Blinky LED