【问题标题】:removing, restoring items in ListView and database删除、恢复 ListView 和数据库中的项目
【发布时间】:2013-08-10 09:29:38
【问题描述】:

我有一个ListView,其中包含动态添加的项目。添加项目时,会将其添加到ListView 并插入到 SQLite 数据库中,以便可以保存列表中的项目。我还可以通过获取项目的位置然后使用该信息删除它来删除特定项目。

这就是我添加项的方式(我使用多个类):

DataModel.class:

public void addItem(Object data) {

        String string = String.valueOf(data);

        mPlanetsList.add(createPlanet("planet", string)); 
        History history = new History();
        history.getDataHashMap().put("planet", data);
        history.addToHistoryDB();

        mHistoryList.add(history);

        if (null != mOnItemAddHandler) {
            mOnItemAddHandler.onItemAdded(data);
        }
    }

History.class:

public void addToHistoryDB() {

        MySQLiteOpenHelper mDbHelper = MySQLiteOpenHelper.getInstance();
        SQLiteDatabase db = mDbHelper.getWritableDatabase();

        ContentValues values = getContentValues();

        rawId = (int) db.insert(TABLE_NAME, COL_ID, values);
        db.close();
    }

这就是我删除项的方式:

DataModel.class:

public void removeItem(int index) { 

        if (mPlanetsList == null || index < 0 || index >= mPlanetsList.size()) {
            return;
        }
        // remove from mPlanetList
        mPlanetsList.remove(index);

        History history = mHistoryList.get(index);
        mHistoryList.remove(index);
        if (null != history) {
            history.remove();
            history = null;
        }

        // notify, the HistoryFragment will update view
        if (null != mOnItemAddHandler) {
            mOnItemAddHandler.onItemRemove(index);
        }

History.class:

public void remove() {
        MySQLiteOpenHelper mDbHelper = MySQLiteOpenHelper.getInstance();
        SQLiteDatabase db = mDbHelper.getWritableDatabase();

        int r = db.delete(TABLE_NAME, "_id = ?",  // delete the int r ??
                new String[] { String.valueOf(rawId) }); 
        db.close();
    }

当应用程序从“最近的应用程序”中删除或重新启动时,会调用 initList() 从数据库中恢复 ListView 项。

这是代码:

DataModel:

private void initList() {



        mHistoryList = History.getList();
        for (int i = 0; i < mHistoryList.size(); i++) {
            Object obj = mHistoryList.get(i).getDataHashMap().get("planet");
            mPlanetsList.add(createPlanet("planet", String.valueOf(obj))); 
        }
    }

History:

public static ArrayList<History> getList() {
        Cursor cursor = null;
        try {
            MySQLiteOpenHelper mDbHelper = MySQLiteOpenHelper.getInstance();
            SQLiteDatabase db = mDbHelper.getWritableDatabase();
            String sql = "select * from " + History.TABLE_NAME;
            ArrayList<History> list = new ArrayList<History>();
            cursor = db.rawQuery(sql, null);
            if (cursor != null) {
                for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor
                        .moveToNext()) {
                    History item = new History();
                    item.fromCuror(cursor);
                    list.add(item);
                }
            }
            return list;
        } finally {
            if (null != cursor && Integer.parseInt(Build.VERSION.SDK) < 14) {
                cursor.close();
            }
        }
    }

只要列表的顺序没有改变,这个方法就可以正常工作——我可以添加项目和删除项目,而且一切正常。但是,我希望将项目添加到列表的顶部而不是底部。

因此,我阅读了有关如何将项目添加到 ListView 顶部的信息,发现通过在添加项目时添加 0 作为位置,新项目将位于列表顶部。

mPlanetsList.add(0, createPlanet("planet", string)); // I put the 0 in wherever the item is added eg when adding from the database

但是,当我这样做时,在 ListView 中查看/删除的项目不会继续与数据库中的数据对应。例如,假设我将三个项目添加到列表中:dog 然后cat 然后horse。 ListView 以正确的顺序显示它们(horse 在顶部)。如果我然后删除一个项目,可以说:cat,ListView 更新并且一切都很好。但是,如果我随后重新启动应用程序,则会调用 initList()。这就是问题所在 - 从列表中删除的不是 cat,而是horsedog

我认为问题的可能点:

a) initList() - 它没有添加正确的项目

b) 在 removeItem() - 它没有从数据库中删除正确的项目。

c) 在 getList() 中 - 可能是带有光标的东西???

这个想法 b) 更有可能,但我不知道问题到底出在哪里,也不知道如何改变它。

编辑:

经过一些测试,我发现我是对的,b) 是错误的地方。

复现步骤:

创建三个项目:cat 然后dog 然后horseListView 以正确的顺序显示它们,即顶部的horse,底部的catDatabase 在顶部显示 cat,在底部显示 horse

当我删除horseListView 的顶部,Database 的底部)时,ListView 会正确更新,但在数据库中它不是 horse 已被删除,而是实际上是 cat

所以因为删除错误,当使用Database恢复ListView时,ListView出现错误。

我希望这能让事情更清楚!

编辑 2:这就是我创建表格的方式:

public static final String TABLE_NAME = "history_table";
    public static final String COL_TITLE = "title";
    public static final String COL_CONTENT = "content";
    public static final String COL_DATE = "date";
    public static final String COL_TYPE = "type";
    public static final String COL_ONGOING = "ongoing";
    public static final String COL_DATA = "data";
    public static final String COL_ID = "_id";

    public static final String DATABASE_CREATE = "create table " + TABLE_NAME
            + "(" + COL_ID + " integer primary key autoincrement, " + COL_TITLE
            + " text not null, " + COL_CONTENT + " text not null, " + COL_DATE
            + " text not null, " + COL_TYPE + " text not null, " + COL_ONGOING
            + " text not null, " + COL_DATA + " text not null  );";

这是 getContentValues():

public ContentValues getContentValues() {

        ContentValues values = new ContentValues();
        values.put(History.COL_TITLE, "MyTitle");
        values.put(History.COL_CONTENT, "MyContent");
        values.put(History.COL_DATE, "Date placeholder");
        values.put(History.COL_TYPE, "QuickNote");
        values.put(History.COL_ONGOING, "Ongoing placeholder");
        values.put(History.COL_DATA, new JSONObject(mDataHashMap).toString());

        return values;
    }

编辑 3:

我基本上把范围缩小到这样一个事实,因为 ListView 和 Database 中的项目顺序不同,按它们在列表中的位置删除项目是行不通的。那么一个可能的解决方案是反转数据库中项目的顺序以匹配 ListView(好主意/可能?)。

编辑 3.1:

https://stackoverflow.com/a/7348117/2442638

这种降序排列可能会有所帮助。我不知道我应该把它放在哪里

编辑 3.5:

我现在可以进行订购了。删除几乎可以工作,但现在有一个问题是第一次删除不起作用。之后的其余工作。我按_id 排序,因为那是autoincrement,它可能从1 或0 开始,而列表从另一个开始。我会做更多的研究

【问题讨论】:

  • 您使用的是什么类型的适配器?另外,与您有关的解释:被删除的猫重新出现在列表中?狗或马还在数据库中吗?您应该在您描述的场景中调试每个操作,并查看数据库是否处于正确的状态。
  • @Luksprog List&lt;Map&lt;String, String&gt;&gt; planetsList 这是我提供给 ListView 时的列表。而且适配器是一个SimpleAdapterSimpleAdapter simpleAdpt = new SimpleAdapter(getActivity(), planetsList, android.R.layout.simple_list_item_1, new String[] { "planet" }, new int[] { android.R.id.text1 });我会试着找出数据库在不同阶段的状态
  • @Luksprog 我的猜测是正确的,b) 是问题所在。重现是相当复杂的,但是 removeItem() 方法删除了错误的项目。我会将问题添加到步骤中。
  • 如何在您的数据库中声明_id 列?是AUTOINCREMENTgetContentValues() 方法长什么样子?
  • @Luksprog 是的,它是autoincrement。我已将 `getContentValues() 发布到问题中

标签: android android-listview sqlite


【解决方案1】:

应用程序中有两个列表:mHistoryListmPlanetsList,您应该保持其中数据项的顺序相同。

您可以通过调用 DataModel 中的方法 addItem 将项目添加到 listview 的顶部:

public void addItem(Object data) {

    History history = new History();
    history.getDataHashMap().put("planet", data);
    history.addToHistoryDB();

    mHistoryList.add(0, history);
    mPlanetsList.add(0, history.createPlanet());

    if (null != mOnItemAddHandler) {
        mOnItemAddHandler.onItemAdded(data);
    }
}

那么新数据会在listview的顶部。

应用重启后,会调用如下代码:

private void initList() {

    mHistoryList = History.getList();
    for (int i = 0; i < mHistoryList.size(); i++) {
        mPlanetsList.add(mHistoryList.get(i).createPlanet());
    }
}

我们应该确保来自History.getList();的数据具有相同的顺序,换句话说,新的数据时间在列表的头部。

所以我们应该把代码改成(order by _id desc):

public static ArrayList<History> getList() {
    Cursor cursor = null;
    try {
        MySQLiteOpenHelper mDbHelper = MySQLiteOpenHelper.getInstance();
        SQLiteDatabase db = mDbHelper.getWritableDatabase();

        // order by _id desc
        String sql = "select * from " + History.TABLE_NAME + " order by _id desc";
        ArrayList<History> list = new ArrayList<History>();
        cursor = db.rawQuery(sql, null);
        if (cursor != null) {
            for (cursor.moveToFirst(); !cursor.isAfterLast(); cursor.moveToNext()) {
                History item = new History();
                item.fromCuror(cursor);
                list.add(item);
            }
        }
        return list;
    } finally {
        if (null != cursor && Integer.parseInt(Build.VERSION.SDK) < 14) {
            cursor.close();
        }
    }
}

【讨论】:

  • 感谢您的回答。我之前尝试过,但我仍然遇到问题(请参阅我的编辑 3.5)我会再次尝试确保我的代码看起来像你的:-)
  • 您发送给我的代码是您使用的代码吗?我看到它没有通过降序获取列表。如果它不是最新的,你会粘贴最新的代码。顺便问一下,我发给你的项目你建好了吗?这符合您的预期吗?
  • @RiThBo 恭喜!
  • 我认为您可以将所有数据放入 Hashmap 中。然后通过不同的键访问数据。
  • 我给你发了一个演示,查看邮件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
  • 1970-01-01
  • 1970-01-01
  • 2018-11-19
  • 1970-01-01
相关资源
最近更新 更多