SQLite更改数据库中项目的排序顺序

时间:2013-03-10 13:00:17

标签: android database sqlite

想象一下,这是我的数据库的快速模型:

enter image description here

数据库中的项目按列表呈现给用户,每个列表显示在新的片段上,这些片段显示在viewpager上。因此,在这个hypotetical案例中,在viewpager上会有两个片段,第一个片段会显示 first_list ,第二个片段会显示 second_list 。这是该查询的代码:

 public static Cursor getListItems (final Context context, String listName) {
    if (mDatabase == null || !mDatabase.isOpen())
        open(context);  //This gets the writable db.

    String where = LIST_NAME + " = '" + listName + "'";
    return mDatabase.query(TABLE_LIST_ITEMS, PROJECTION_LIST_ITEMS, 
    where, null, null, null, SORT_ORDER);
}

SORT_ORDER order_in_list的位置,开始时效果很好。

现在,列表视图可以使用公共library重新排列,它试图允许用户控制每个列表中项目的顺序。这是我遇到问题的地方,光标没有add(int index, Object object),或者其他一些简单的方法来管理排序。我首先想到我可以简单地调用mDatabase.update()来更改order_in_list的值,但这样可行,但结果并非如预期。例如,用户拖动第二项以定位,记住:零指数值,我们现在拥有两个项{{1}为零。虽然我可以在第一项上致电order_in_list以将其职位更新为一个,但想象一下,在一个以上的项目上处理多个项目需要做多少工作形成数据库。

有没有人对如何解决这个问题有任何好的建议?我认为通过添加额外的col用于分类目的我很聪明:(

INB4:

是的,我知道数组处理得好。但是数据库不仅存储4个cols,还有更多的字段。每次从数据库填充数组都是浪费时间和精力。无论如何,当应用程序关闭时,我会写回数据库。

编辑所以我将listview更改为仅显示一个文本字符串,并在实际单击该项目时显示更多列(因此显示具有指定列表项数据的新片段)。这使我可以简单地保留一个可以轻松处理拖放的ArrayAdapter。在onStop期间,只有在需要保存的更改时才更新引用:

mDatabase.update()

其中MoveListItemTo更新order_in_list的值:

@Override
public void onStop() {
    if (updateDbOnExit) {
        //Update rows on database.
        for (int i = 0; i < items.size(); i++) {
            //Set the order in list be the actual order on the array.
            Constants.LogMessage("Updating db content");
            DbManager.moveListItemTo(getActivity(), items.get(i), i);
        }
            updateDbOnExit = false;
    }
    super.onStop();
}   

这将暂时有用。但是,我仍然有兴趣知道是否有其他方法,特别是当例如适配器使用数据库中超过一个列的数据时,因此需要使用CusorAdapter和不是常规的ArrayAdapter,而是需要数据库本身在每次拖放时更新,以通过 public static void moveTaskItemTo (final Context context, String item, int to) { if (mDatabase == null || !mDatabase.isOpen()) open(context); String where = COL_CONTENT + " = '" + item+ "'"; ContentValues mContentValues = new ContentValues(); mContentValues.put(ORDER_IN_LIST, to); int rows = mDatabase.update(TABLE_LIST_ITEMS, mContentValues, where, null); Constants.LogMessage(rows + " row updated. Item moved to position: " + to); close(); } 反映UI上的更改。如上所述,每次拖动时更新数据库中所有的项目(实际上通常不会发生这种情况),这是非常昂贵的,只更新两个行,一个更健全的选择。

2 个答案:

答案 0 :(得分:4)

I just meant I wanted a more effective way to update the fields in the db, rather than manually updating each and every single row

使用户指定的顺序列为小数,而不是整数。然后,您只需要更新已移动的行。

允许负数。

0.00 cat
1.00 aardvark
2.00 wolf
3.00 dog

如果“狗”被拖到“狼”之上,那么“狗”变为1.50并且不需要改变其他行。如果将“aardvark”拖到“cat”之上(特殊情况 - 前置到列表而不是在行之间插入),则从最顶层的值中减去1,“aardvark”变为-1.00。

这将要求您知道相邻行的值,但您不必更新它们。只有移动的行的值必须更改。

答案 1 :(得分:1)

我建议您有一个额外的列user_specified_order,它代表用户通过拖放操作重新排序UI中的行。

如果通过拖放重新定位使user_specified_order值无效,则必须更新每一行。何时持久该值取决于您 - 无论是在用户操作的“结束”,还是定义(例如,单击“保存”按钮),或者在每次拖放后如果没有clearcut操纵结束的UI指示。

编辑:Android中的ContenProvider:  Android - Can you update a Cursor for SQLite results?

Android SQLite交易: Android Database Transaction