【问题标题】:How to store items position in a RecyclerView after drag&drop拖放后如何将项目位置存储在 RecyclerView 中
【发布时间】:2019-07-05 17:35:36
【问题描述】:

我有一个简单的待办事项列表应用程序,其中包含一个 RecyclerView/FirestoreRecyclerAdapter/ItemTouchHelper,其中包含项目 A、B、C、D(见附图)。现在我想将这些项目的位置有效地存储在 Firestore 中,最初是在我添加项目时以及垂直拖放它们时。我如何在概念上或使用现有/示例代码来做到这一点。将它存储在云中很重要,这样如果我从另一台设备上查看它,项目的位置就会保持不变。

关于它的一些想法: 适配器位置 (int) 从 0 开始(在本例中为 D)。当我添加项目 E 时,它的适配器位置为 0,并且所有其他项目的位置都发生了变化。因此,每次添加新项目时,Firestore 中的存储位置可能会增加 1,该项目将显示在顶部。但是,如果我有成千上万的项目(例如在照片库应用程序中)怎么办。每次拖拽物品时更新所有物品的位置是否有效?

我想这应该是一个非常普遍的问题。

我的 Todo 应用程序的 MainActivity (https://i.stack.imgur.com/o3jJ1.jpg)

这是我的 ItemTouchHelper.Callback onMoved() 方法的代码:

@Override
        public void onMoved(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, int fromPos, @NonNull RecyclerView.ViewHolder target, int toPos, int x, int y) {
            super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y);

            for (int maxItems = recyclerView.getChildCount(), i = 0; i < maxItems; ++i) {
                RecyclerView.ViewHolder holder = recyclerView.getChildViewHolder(recyclerView.getChildAt(i));
                int layoutPosition = holder.getLayoutPosition();
                int adapterPosition = holder.getAdapterPosition();
                TodoAdapter.TodoHolder h =  (TodoAdapter.TodoHolder)holder;
                String documentID = h.getDocumentID();
                TextView textViewTitle = (TextView)h.itemView.findViewById(R.id.todo_title);
                CharSequence title = textViewTitle.getText();

                DocumentReference docRef = mFirestore.collection("todos").document(documentID);
                docRef.update("position", adapterPosition);
            }
        }

【问题讨论】:

    标签: android-recyclerview google-cloud-firestore position items


    【解决方案1】:

    现在我想将这些项目的位置有效地存储在 Firestore 中,最初是在我添加项目时以及我垂直拖放它们时。

    虽然这在技术上是可行的,但我不认为 Firestore 是解决此问题的最佳选择,因为 Firestore 中的所有内容都与读写次数有关。因此,每次更改项目的位置时,都会执行与剩余项目数量相等的写入操作。试着看看Firebase realtime database。两者配合得很好。

    我怎样才能在概念上做到这一点

    只需为每个元素添加一个顺序编号属性,表示列表中的位置,然后根据该属性对它们进行排序(升序或降序)。将元素从一个位置移动到另一个位置后,将每个剩余对象的位置更新一个。

    将它存储在云中很重要,这样如果我从另一台设备上查看它,项目的位置就会保持不变。

    如果您将所有元素保持有序,那么每个用户都将能够看到相同的排列。

    所以每次添加新项目时,Firestore 中的存储位置可能会增加 1

    对了,每次添加一个新项目,位置都会增加一个。

    每次拖拽物品时更新所有物品的位置是否有效?

    在列表的开头更新项目的位置肯定会非常昂贵。让我们举个例子。假设您有一个包含 1000 个项目的集合,并且您想要添加一个新项目作为列表中的第二个项目。这意味着您需要为添加项目支付一次写入操作以及另外 999 次写入操作以更新剩余 999 项的位置。因此,总共将收取 1000 次写入操作的费用。这是否符合您的需求由您决定。

    【讨论】:

    • 谢谢亚历克斯。我将查看 Firebase 实时数据库的文档。但与此无关,我在我的 onMoved 方法实现的代码上方添加了。移动完成后,recyclerView 子项的迭代没有向我显示正确的 ViewHolders 序列。这里有什么问题?
    • 如果没有看到您的数据库结构和适配器类,我看不出您的代码有什么问题。即使您向我提供该信息,这也不是可以在评论中回答的问题。因此,请使用自己的MCVE 发布另一个新问题,以便我和其他 Firebase 开发人员可以帮助您。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 2015-12-06
    相关资源
    最近更新 更多