Android Studio,使用Firebase实时数据库和存储,如何重新排列列表。

huangapple go评论73阅读模式
英文:

Android studio, using firebase realtime database and storage, how to re-arange list

问题

我正在实时数据库中保存一个数组列表,并希望为用户添加选择和删除对象的选项,例如,我有5个对象(索引0到4),我想删除索引2。问题是,我如何重新排列数据库中的列表,因为如果不这样做,就会出现间隙,我将会有索引0、1,然后3、4。每个对象都有上传到存储的图像的URL,并且我将它们保存在与对象相同的索引上。

总之,我想重新排列存储和实时数据库中的列表,这可能吗?如果可以,该如何做?

我尝试用模型自身的更新后的数组列表覆盖列表引用,这显然可以工作,但主要问题在于存储。

例如:

我在数据库中有5个索赔:

Android Studio,使用Firebase实时数据库和存储,如何重新排列列表。

而在存储中也有相同的5个索引与图像:

Android Studio,使用Firebase实时数据库和存储,如何重新排列列表。

因此,如果我想删除索引2,然后使其成为0到3而没有间隙。

英文:

I am saving an array list at the realtime database, and I want to add an option for the user to select and delete an object, for examples I have 5 objects (indexes 0 to 4) and I want to delete index 2. The question is how I can re-arrange the list at the database because if I will not do so there will be a gap, I will have the indexes 0,1 and then 3,4. Every object have url of images that I uploading to the storage and I save them at indexes of the same indexes as the object.
At bottom line I want to re-arrange the list at the storage and the real-time database, it is possible? if so, how?

I tried to override the list reference with the updated array list from the model it self, and it works obviously but the problem is with the storage mostly.

For example:

I have 5 claims at the database:

Android Studio,使用Firebase实时数据库和存储,如何重新排列列表。

And the same 5 indexes at the storage with the images

Android Studio,使用Firebase实时数据库和存储,如何重新排列列表。

So if I would like to delete index 2 and then make it to be 0 to 3 with no gaps.

答案1

得分: 0

在你目前的设置中,从序列中移除一个键意味着你必须重新编号其后的所有键。除非改变数据结构,否则无法避免这一点,因此常用的方法是读取“claims”节点,在你的应用代码中对其进行更改,然后将整个“claims”节点写回数据库。

我建议不要为 Firebase 实时数据库中的键使用顺序数字值,原因正如你提到的那样。事实上,使用顺序数字键是已记录的反模式,例如在此 2014 年的博客文章中有详细说明:最佳实践:Firebase 中的数组


更好的建模顺序的方式是在每个子节点中存储一个值,指示其相对位置。最初,该值可以是你现在用作键的值,但是以浮点数值的形式。因此:

"claims": {
  "-Nasdak...": {
    "index": "1.0",
    ...
  },
  "-Nbisai..": {
    "index": "2.0",
    ...
  },
  "-Ncsadu...": {
    "index": "3.0",
    ...
  }
}

因此,这里使用推送 ID 作为键,并在每个键下存储相对索引。有了这个结构,你可以:

  • 使用 orderByChild('index') 来获得有序的结果。
  • 移除任何索引,结果仍然可用。
  • 将项目移动到不同位置,方法是使其index 值位于两个(新的)相邻节点之间的中间位置。

对于最后一种操作的示例:假设我们将上面示例中的第一个节点移动到其他两个节点之间,结果将是:

"claims": {
  "-Nasdak...": {
    "index": "1.5",
    ...
  },
  "-Nbisai..": {
    "index": "2.0",
    ...
  },
  "-Ncsadu...": {
    "index": "3.0",
    ...
  }
}

这里只有 index 值发生了变化。

这种方法需要记住的唯一一点是,这只适用于一定数量的交换(取决于你的平台),直到你遇到浮点精度限制为止。我通常还没有达到这种限制,而在我担心的情况下,偶尔重新索引(基于时间或交换计数)会解决问题。


对于 Cloud Storage 存储桶中的文件夹,我实际上只需将文件夹的名称/路径添加到数据库中相关的节点中:

"-Nasdak...": {
  "index": "1.5",
  "storageFolder": "path/to/folder",
  ...
}

使用与键无关的名称/路径意味着你必须查找该路径,但这是一个恒定的成本 - 而在存储中移动/重命名文件夹将更糟糕,因为大多数这些系统实际上并没有本地的移动操作。例如,在云存储 SDK 实现移动 API 的平台上,它是作为复制/粘贴/删除原始数据序列实现的。

英文:

In your current setup, removing a key from the sequence means that you have to renumber all the keys after it. There is no way around this without changing your data structure, so the common approach would be to read the claims node, change it in your application code, and write the entire claims node back to the database.

My recommendation is to not use sequential numeric values for the keys in your Firebase Realtime Database, precisely for the reasons you mention. In fact, using sequential numeric keys is documented anti-pattern, for example in this blog post from 2014: Best Practices: Arrays in Firebase.


The better way to model this ordering is to store a value in each child nodes that indicates its relative position. Initially that value could be the value that you now use as a key, but then as a floating point value. So:

"claims": {
  "-Nasdak...": { // 👈 push key
    "index": "1.0",
    ...
  },
  "-Nbisai..": { // 👈 push key
    "index": "2.0",
    ...
  },
  "-Ncsadu...": { // 👈 push key
    "index": "3.0",
    ...
  },
}

So this uses push IDs for the keys, and stores the relative index in a property under each key. With this structure you can:

  • Use orderByChild('index') to get the ordered result.
  • Remove any index, and the result will still work.
  • Move an item to a different position, by making its index value the middle between the two (new) neighboring nodes.

An example for that last operation: say that we move the first node in the above example to between the other two nodes, the result would be:

"claims": {
  "-Nasdak...": {
    "index": "1.5", // 👈 changed value
    ...
  },
  "-Nbisai..": {
    "index": "2.0",
    ...
  },
  "-Ncsadu...": {
    "index": "3.0",
    ...
  },
}

Nothing but that one index value changed here.

The only think to keep in mind with this approach is that this only works for a certain number of swaps (depending on your platform) until you run into floating point precision limits. I usually don't reach such limits yet, and in the cases where I worried - an occasional re-indexing (time-based or swap-count based) - solved it.


For the folders in your Cloud Storage bucket, I would actually just add the name/path of the folder into the relevant node(s) in the database:

"-Nasdak...": {
  "index": "1.5",
  "storageFolder": "path/to/folder" // 👈
  ...
},

Using a name/path not related to the key means that you will have to look up that path, but that's a constant cost - while having to move/rename folders in Storage will be much worse as most of these systems don't really have native move operations. For example, on platforms where Cloud Storage SDKs implement a move API, it is implemented as a copy/paste/delete-original-data sequence.

huangapple
  • 本文由 发表于 2023年6月9日 02:15:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76434658.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定