java - 如何在节点 Firebase 中获得唯一的随机产品?
问题描述
数据:
- products
- -L74Pc7oVY22UsCETFBv
- name: "gjwj"
- category: "hreggrrg"
- location: "vjhiwehifwe"
- price: 44
- color: fassaf
- -L74uJ7oVYcVNyCteFBz
- name: "uygfwh"
- category: "hhhjwwwom"
- location: "pervrr"
- price: 33
- color: yrtrr
......................
我在 node 有很多产品products
,超过 1000 种产品。我可以全部显示在ListView
. 我只想向用户显示一个唯一的随机数,例如亮点,但不是全部下载,只有一个。
代码:
ValueEventListener v = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot child : dataSnapshot.getChildren()) {
String name = (String) child.child("name").getValue().toString();
Toast.makeText(MainActivity.this, name, Toast.LENGTH_SHORT).show();
//How to get?????
}
}
@Override
public void onCancelled(DatabaseError databaseError) {}
};
FirebaseDatabase.getInstance().getReference().addListenerForSingleValueEvent(v);
如何在节点 Firebase 中获得唯一的随机产品?
解决方案
好吧,这里有一些关于 SOF 的好答案,但它们是分开的,所以我将尝试用两种方法回答你的问题。
但首先,在编写一些代码之前,我可以告诉您此代码不起作用,因为您在参考中缺少一个子节点products
,也就是说,显然假设该products
节点是您的 Firebase 数据库根目录的直接子节点。
实际答案:
假设您的数据库结构如下所示(其中products
节点是 Firebase 数据库的直接子节点):
Firebase-root
|
--- products
|
--- productIdOne
| |
| --- name: "gjwj"
| |
| --- category: "hreggrrg"
| |
| --- location: "vjhiwehifwe"
| |
| --- price: 44
| |
| --- color: "fassaf"
|
--- productIdTwo
| |
| --- name: "uygfwh"
| |
| --- category: "hhhjwwwom"
| |
| --- location: "pervrr"
| |
| --- price: 33
| |
| --- color: "yrtrr"
|
--- //And so on
要获得随机产品,请使用以下代码:
ListView listView = (ListView) findViewById(R.id.list_view);
ArrayAdapter arrayAdapter = new ArrayAdapter<>(context, android.R.layout.simple_list_item_1, randomProductList);
listView.setAdapter(arrayAdapter);
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference productsRef = rootRef.child("products"); //Added call to .child("products")
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<String> productList = new ArrayList<>();
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String name = ds.child("name").getValue(String.class);
productList.add(name);
}
int productListSize = productList.size();
List<String> randomProductList = new ArrayList<>();
randomProductList.add(new Random().nextInt(productListSize)); //Add the random product to list
arrayAdapter.notifyDatasetChanged();
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG, "Error: ", task.getException()); //Don't ignore errors!
}
};
productsRef.addListenerForSingleValueEvent(valueEventListener);
为了获得所有产品,您需要遍历节点的所有子products
节点。所以调用child("products")
是强制性的。
如果您想要多个随机产品,那么您可以创建一个循环并在randomProductList
.
这被称为经典解决方案,您可以将其用于仅包含少量记录的节点,但如果您害怕获取大量数据,那么我会向您推荐第二种方法。这还涉及通过添加一个名为productIds
. 您的数据库结构应如下所示:
Firebase-root
|
--- products
| |
| --- productIdOne
| | |
| | --- //details
| |
| --- productIdTwo
| |
| --- //details
|
--- productIds
|
--- productIdOne: true
|
--- productIdTwo: true
|
--- //And so on
因此,正如您在问题中提到的,如果您想避免下载products
包含具有所有属性的所有产品的整个节点,则必须创建一个名为productIds
. 因此,要获得单个产品,您只需下载一个仅包含产品 ID 的简单节点。
这种做法称为非规范化(复制数据),是 Firebase 的常见做法。为了更好地理解,我建议您观看此视频,Firebase 数据库的非规范化是正常的。
但是请记住,就像您在这个新创建的节点中添加随机产品一样,您需要在不再需要它们时删除它们。
因此,要获得随机产品,您需要查询数据库两次。请看下面的代码:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference productIdsRef = rootRef.child("productIds");
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<String> productIdsList = new ArrayList<>();
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String productId = ds.getKey();
productIdsList.add(productId);
}
int productListSize = productList.size();
List<String> randomProductList = new ArrayList<>(););
DatabaseReference productIdRef = rootRef.child("products").child(productIdsList.get(new Random().nextInt(int productListSize));
ValueEventListener eventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
String name = dataSnapshot.child("name").getValue(String.class);
Log.d("TAG", name);
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG, "Error: ", task.getException()); //Don't ignore errors!
}
};
productIdRef.addListenerForSingleValueEvent(eventListener);
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG, "Error: ", task.getException()); //Don't ignore errors!
}
};
productIdsRef.addListenerForSingleValueEvent(valueEventListener);
当您对 Firebase 数据库执行查询时,可能会有多个结果。所以dataSnapshot
包含这些结果的列表。即使只有一个结果,该dataSnapshot
对象也将包含一个结果列表。
推荐阅读
- javascript - 在 React Native 中根据表单提交处理按钮
- google-chrome - 为什么将帖子提取到 Dropbox UploadSession 端点仅适用于 Mozilla Firefox 而不适用于 Chrome?
- usb - 自定义 HID 游戏手柄适用于 Windows,在 Linux 中有一些倒置按钮
- java - 如何在 Spring 中限制方法调用?
- javascript - React 小吃店显示在 poup 后面
- pandas - 如何将分类列转换为列多索引的级别 0
- excel - 在 Google 表格中使用 Arrayformula 的迭代计数器
- regex - 正则表达式拆分 CPU 使用率字符串,没有百分比
- linux - 缺少 Databricks ODBC 驱动程序
- javascript - 将值传递给存储在 Android 资产文件夹中的 HTML 文件