Android 在Listview上选择了错误的项目

Android 在Listview上选择了错误的项目,android,listview,simplecursoradapter,onitemclick,Android,Listview,Simplecursoradapter,Onitemclick,面对一个非常奇怪的问题。我在每个项目上都有一个带有复选框的listview,当我点击listview的第一个项目时,它被选中,但与此项目一起,listview的最后一个项目也被选中当我滚动列表视图时。没有卷轴,它工作得很完美 另外,当我选择最后一个项目时,第一个项目将在滚动后与它一起被选择。请注意,第一个和最后一个之间的所有其他项目都正常工作。有趣的是,在选择了第一个或最后一个项目后,如果我不滚动列表视图2-3秒,那么它就工作得很好了。。所以我认为这可能是视图渲染的问题,或者有些问题。谁能告诉我

面对一个非常奇怪的问题。我在每个项目上都有一个带有
复选框的
listview
,当我点击
listview的第一个项目时,它被选中,但与此项目一起,listview的最后一个项目也被选中当我滚动列表视图时。没有卷轴,它工作得很完美

另外,当我选择最后一个项目时,第一个项目将在滚动后与它一起被选择。请注意,第一个和最后一个之间的所有其他项目都正常工作。有趣的是,在选择了第一个或最后一个项目后,如果我不滚动
列表视图
2-3秒,那么它就工作得很好了。。所以我认为这可能是视图渲染的问题,或者有些问题。谁能告诉我这到底是怎么回事

Cursor cursor = queryDatabase();

    // The desired columns to be bound
      String[] columns = new String[] {               
        DataBaseHelper.ROW_PROFILE_NAME,
        DataBaseHelper.ROW_PROFILE_TYPE,
        DataBaseHelper.ROW_ID
      };

      // the XML defined views which the data will be bound to
      int[] to = new int[] { 
        R.id.profileName,
        R.id.profileStatus
      };

      // create the adapter using the cursor pointing to the desired data 
      //as well as the layout information
      mAdapter = new SimpleCursorAdapter(
        this, R.layout.profile_listview_delete_item, 
        cursor, 
        columns, 
        to,
        0);

      listView = (ListView) findViewById(R.id.profile_listview_delete_main);
      // Assign adapter to ListView
      listView.setAdapter(mAdapter);

      listView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int position, long arg3) {
            // TODO Auto-generated method stub

            CheckBox cb;                

            Cursor c = mAdapter.getCursor();
            String prodile_id = c.getString(c.getColumnIndex(DataBaseHelper.ROW_ID));

            cb = (CheckBox)arg1.findViewById(R.id.checkbox);
            cb.toggle();

            if(cb.isChecked())
            {                   
                profileStack.add(prodile_id);                   
                //Toast.makeText(getApplicationContext(), String.valueOf(profileStack), Toast.LENGTH_LONG).show();                  
                counter++;              
            }
            else if(!cb.isChecked())
            {
                profileStack.remove(prodile_id);                    
                //Toast.makeText(getApplicationContext(), String.valueOf(profileStack), Toast.LENGTH_LONG).show();                  
                counter--;                  
            }               
            countSelectedItem.setText(String.valueOf(counter)+" items selected");

            mAdapter.notifyDataSetChanged();                                
        }
    });
Cursor Cursor=queryDatabase();
//要绑定的所需列
字符串[]列=新字符串[]{
DataBaseHelper.ROW\u PROFILE\u名称,
DataBaseHelper.ROW\u PROFILE\u类型,
DataBaseHelper.ROW\u ID
};
//数据将绑定到的XML定义的视图
int[]到=新的int[]{
R.id.profileName,
R.id.profileStatus
};
//使用指向所需数据的光标创建适配器
//以及布局信息
mAdapter=新的SimpleCursorAdapter(
此,R.layout.profile\u列表视图\u删除\u项,
光标,
柱,
到
0);
listView=(listView)findViewById(R.id.profile\u listView\u delete\u main);
//将适配器分配给ListView
setAdapter(mAdapter);
setOnItemClickListener(新的OnItemClickListener(){
@凌驾
public void onItemClick(适配器视图arg0、视图arg1、内部位置、长arg3){
//TODO自动生成的方法存根
复选框cb;
游标c=mAdapter.getCursor();
String profile_id=c.getString(c.getColumnIndex(DataBaseHelper.ROW_id));
cb=(复选框)arg1.findViewById(R.id.CheckBox);
cb.toggle();
if(cb.isChecked())
{                   
profileStack.add(profile_id);
//Toast.makeText(getApplicationContext(),String.valueOf(profileStack),Toast.LENGTH_LONG.show();
计数器++;
}
如果(!cb.isChecked())
{
profileStack.remove(profile_id);
//Toast.makeText(getApplicationContext(),String.valueOf(profileStack),Toast.LENGTH_LONG.show();
计数器--;
}               
countSelectedItem.setText(String.valueOf(counter)+“所选项目”);
mAdapter.notifyDataSetChanged();
}
});

您应该使用一个自定义的
适配器
(以及一个模型类,它是
可选的
。这里
TemaRescatado
是snippet中的一个模型类)。在
getView(…)
中,您必须使用try-to-use

代码片段

viewHolder.checkbox = (CheckBox) view.findViewById(R.id.checkBox1);
viewHolder.checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {

      @Override
      public void onCheckedChanged(CompoundButton buttonView,
         boolean isChecked) {
         TemaRescatado element = (TemaRescatado) viewHolder.checkbox
                  .getTag();
         element.setSelected(buttonView.isChecked());

         }
      });

您应该从AdapterView获取光标,它作为参数传递给onItemClick方法

更改代码

Cursor c = mAdapter.getCursor();


发生此问题的原因是
ListView
的回收。当第一个可见的
视图不可见时,它将重新使用该视图,以显示适配器的下一个数据。因此,当您选中并选中
列表
位置中的数据时。它将保持与您离开时相同的状态。因此,我对这个问题的解决方案是:

在适配器的
getView()中

放置一个简单的if-else语句,检查是否应选中复选框,如下所示:

// note that this is a pseudo code
if(ID exist in profileStack){
//set checkBox
}
else{
//set checkBox
}

你能发布你的适配器类吗?我想这是视图持有者模式的问题吗?@Rajesh,我使用的是SimpleCrsorAdapter,因为你可以看到上面的代码。你的代码方式是错误的。您必须使用自定义适配器和viewholder类,从该适配器更改复选框的值时,您必须从适配器更改此复选框的字段值。单击listview后,从适配器获取位置和值。检查:。可能重复的。是否可以更正当前代码的问题?因为我告诉过所有其他项目都工作得很好。我不确定,但是,定制适配器不可能更好,因为它将优化您的代码并实现
ViewHolder
pattern
ListView的
滚动将平滑。您可以在
notifyDataSetChanged()之后使用
mAdapter.notifyDataSetInvalidated()
。正如@kaushik建议的那样……使用viewholder,否则您将得到不想要的result@kaushik,notifyDataSetInvalidated()也不起作用,我知道ViewHolder可能会解决此问题,但更改最终应用程序的代码将是一项漫长的任务!不,它不会改变情况。更新了我的答案。检查这个,让我知道它正在工作或不工作。不,它不工作。还是一样,选中第一项,然后滚动浏览,看到最后一项也被选中了!但检查第一项,等待2秒钟,滚动浏览,然后看到它工作良好!奇怪的
// note that this is a pseudo code
if(ID exist in profileStack){
//set checkBox
}
else{
//set checkBox
}