ListView和BaseAdapter实现显示重复元素

时间:2014-06-20 06:55:25

标签: android android-listview baseadapter

我的自定义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();
    }
}

4 个答案:

答案 0 :(得分:2)

在添加新元素之前尝试清除数组

  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();
   }

正如你所说的那样,它第一次完美地检索,但是第二次并且开始提供重复值。这可能是由于您使用的是类变量 gridArray 。检查方法中的第一行,在添加新数据集之前删除所有元素

答案 1 :(得分:0)

可能发生这种情况是因为当您致电retrieveCurrentGoals()时,您始终会阅读数据库中的所有行并将其附加到gridArray

最初你添加了第一项, 在第二次你添加了第一和第二 等等。

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

答案 2 :(得分:0)

Cursor中的getGoalData()是否有预期的长度(前一个长度+ 1)?

我强烈建议您使用CursorLoader课程并在LoaderCallbacksActivity中实施Fragment

答案 3 :(得分:0)

在添加数据之前,您应该清理数组。因为离开并再次来到当前活动或片段将导致每次在阵列中添加数据,这就是为什么你得到了dublicate data.just清理你的gridarray和目标数据,然后再添加数据。就是这样。 / p>