Android 显示重复元素的ListView和BaseAdapter实现

Android 显示重复元素的ListView和BaseAdapter实现,android,android-listview,baseadapter,Android,Android Listview,Baseadapter,我有一个由自定义BaseAdapter实现支持的ListView,它背后有一个数据库。当我第一次将项目插入数据库时,一切正常。但是,当我添加另一项时,我的ListView突然显示3项而不是2项。如果我添加另一个项目,ListView会更新,突然我看到5个项目。当我点击后退按钮并返回到上一个活动并再次启动ListView活动时,它会再次显示正确的项目数。因此,我的ListView或适配器没有正确更新,但我看不出哪里出了问题。我非常感谢你的帮助 我的代码: @Override protect

我有一个由自定义BaseAdapter实现支持的ListView,它背后有一个数据库。当我第一次将项目插入数据库时,一切正常。但是,当我添加另一项时,我的ListView突然显示3项而不是2项。如果我添加另一个项目,ListView会更新,突然我看到5个项目。当我点击后退按钮并返回到上一个活动并再次启动ListView活动时,它会再次显示正确的项目数。因此,我的ListView或适配器没有正确更新,但我看不出哪里出了问题。我非常感谢你的帮助

我的代码:

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.goals_main_screen);
    mListView = (ListView) findViewById(R.id.goal_listview);
    customGridAdapter = new CustomGridViewAdapter(this, R.layout.card_grid_item, gridArray);
    customGridAdapter.registerDataSetObserver(new DataSetObserver(){
        @Override
        public void onChanged(){
            retrieveCurrentGoals();
        }
    });
    mListView.setAdapter(customGridAdapter);
    mListView.setOnItemClickListener(new OnItemClickListener(){
        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
            goToDetailedGoalView((int) id);
        }
    });
    retrieveCurrentGoals();
}

private void retrieveCurrentGoals(){
    String[] projection = {DatabaseHelper.KEY_ROWID, DatabaseHelper.KEY_GOAL_ID};
    Cursor c = getContentResolver().query(MyContentProvider.CONTENT_URI_USER_GOALS, projection, null, null, null);
    c.moveToFirst();
    for(int i=0; i<c.getCount();i++){
        String [] goalData = getGoalData(c.getInt(1));
        gridArray.add(goalData);
        c.moveToNext();
    }
    c.close();
}

private String[] getGoalData(int id){
    String[] projection = {DatabaseHelper.KEY_GOAL_TITLE, DatabaseHelper.KEY_GOAL_CATEGORY};
    String selection = "_id = " + id;
    Cursor c = getContentResolver().query(MyContentProvider.CONTENT_URI_GOALS, projection, selection, null, null);
    if(c.moveToFirst()){
        String[] data = {"", "", ""};
        data[0] = c.getString(0);
        data[1] = Integer.toString(c.getInt(1));
        data[2] = String.valueOf(id);
        return data;
    }
    c.close();
    return null;
}

private void goToDetailedGoalView(int id){
    Intent i = new Intent(this, GoalCardDetail.class);
    i.putExtra(SharedData.GOAL_ID.getValue(), id);
    startActivityForResult(i, 0);
}

public void toGoalSelectionScreen(View v){
    Intent i = new Intent(this, DisplayCardActivity.class);
    startActivityForResult(i,GO_TO_GOAL_CARD_SCREEN);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
    if(requestCode == GO_TO_GOAL_CARD_SCREEN && resultCode == RESULT_OK){
        System.out.println("ListView holds: " + mListView.getCount());
        customGridAdapter.notifyDataSetChanged();
    }
}
@覆盖
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.goals\u主屏幕);
mListView=(ListView)findViewById(R.id.goal\u ListView);
customGridAdapter=新的CustomGridViewAdapter(此,R.layout.card\u grid\u项,gridArray);
customGridAdapter.registerDataSetObserver(新的DataSetObserver(){
@凌驾
更改后的公共无效(){
检索当前目标();
}
});
setAdapter(customGridAdapter);
setOnItemClickListener(新的OnItemClickListener(){
@凌驾
public void onItemClick(AdapterView父级、视图、,
内部位置,长id){
goToDetailedGoalView((int)id);
}
});
检索当前目标();
}
私有void retrieveCurrentGoals(){
String[]projection={DatabaseHelper.KEY\u ROWID,DatabaseHelper.KEY\u GOAL\u ID};
游标c=getContentResolver().query(MyContentProvider.CONTENT\u URI\u USER\u目标,投影,null,null);
c、 moveToFirst();

对于(int i=0;i在添加新元素之前尝试清除数组

  private void retrieveCurrentGoals(){
     gridArray.clear();
     String[] projection = {DatabaseHelper.KEY_ROWID, DatabaseHelper.KEY_GOAL_ID};
     Cursor c = getContentResolver().query(MyContentProvider.CONTENT_URI_USER_GOALS, projection, null, null, null);
     c.moveToFirst();
     for(int i=0; i<c.getCount();i++){
       String [] goalData = getGoalData(c.getInt(1));
       gridArray.add(goalData);
       c.moveToNext();
     }
    c.close();
   }
private void retrieveCurrentGoals(){
gridArray.clear();
String[]projection={DatabaseHelper.KEY\u ROWID,DatabaseHelper.KEY\u GOAL\u ID};
游标c=getContentResolver().query(MyContentProvider.CONTENT\u URI\u USER\u目标,投影,null,null);
c、 moveToFirst();

对于(int i=0;i可能是因为调用
retrieveCurrentGoals()
时,您总是读取数据库中的所有行,并将它们附加到
gridArray

最初您添加了第一项, 在第二次添加第一和第二个 等等


作为一种可能的解决方案,在设置新数据之前调用
clear
方法
arrayList

getGoalData()
中的
光标是否具有预期的长度(以前的长度+1)


我强烈建议在
活动
片段
中使用
CursorLoader
类并实现
LoaderCallbacks
,在将数据添加到数组中之前,您应该清理数组。因为每次离开并再次来到当前活动或片段都会导致在数组中添加数据,因此这就是为什么您会得到复杂的数据。在添加数据之前,只需清理gridarray和目标数据。就这样。

啊,这解决了问题。谢谢!