如何在节点Firebase中获取独特的随机产品?

时间:2018-05-18 14:05:34

标签: java android firebase firebase-realtime-database

数据:

- products
   - -L74Pc7oVY22UsCETFBv
       - name: "gjwj"
       - category: "hreggrrg"
       - location: "vjhiwehifwe"
       - price: 44
       - color: fassaf
   - -L74uJ7oVYcVNyCteFBz
       - name: "uygfwh"
       - category: "hhhjwwwom"
       - location: "pervrr"
       - price: 33
       - color: yrtrr
   ......................

我在节点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中获取唯一随机产品?

1 个答案:

答案 0 :(得分:2)

嗯,这里有一些关于SOF的好答案但是是分开的,所以我会尝试用两种方法回答你的问题。





但首先,在编写一些代码之前,我可以告诉你这段代码没有用,因为你在引用中是一个孩子,这是 products ,显然假设 products 节点是您的Firebase数据库根目录的直接子项。





实际答案:





假设您的数据库结构如下所示(其中 products 节点是Firebase数据库的直接子节点):




  Firebase -root
 |
 ---产品
 |
 --- productIdOne
 | |
 | ---名称:“gjwj”
 | |
 | ---类别:“hreggrrg”
 | |
 | ---位置:“vjhiwehifwe”
 | |
 | ---价格:44
 | |
 | ---颜色:“fassaf”
 |
 --- productIdTwo
 | |
 | ---名称:“uygfwh”
 | |
 | ---类别:“hhhjwwwom”
 | |
 | ---位置:“pervrr”
 | |
 | ---价格:33
 | |
 | ---颜色:“yrtrr”
 |
 --- //依旧
  




要获得随机产品,请使用以下代码:


 

 <代码>列表与LT;字符串&GT; randomProductList = new ArrayList&lt;&gt;();&#xA; ListView listView =(ListView)findViewById(R.id.list_view);&#xA; ArrayAdapter arrayAdapter = new ArrayAdapter&lt;&gt;(context,android.R.layout。 simple_list_item_1,randomProductList);&#xA; listView.setAdapter(arrayAdapter);&#xA; DatabaseReference rootRef = FirebaseDatabase.getInstance()。getReference();&#xA; DatabaseReference productsRef = rootRef.child(“products”); //添加了对.child(“products”)的调用&#xA; ValueEventListener valueEventListener = new ValueEventListener(){&#xA; @越权#XA; public void onDataChange(DataSnapshot dataSnapshot){&#xA;列表与LT;字符串&GT; productList = new ArrayList&lt;&gt;();&#xA; for(DataSnapshot ds:dataSnapshot.getChildren()){&#xA; String name = ds.child(“name”)。getValue(String.class);&#xA; productList.add(名称);&#XA; }&#XA;&#XA; int productCount = productList.size();&#xA; int randomNumber = new Random()。nextInt(productCount);&#xA;&#xA; randomProductList.add(productList.get(randomNumber)); //将随机产品添加到列表&#xA; arrayAdapter.notifyDatasetChanged();&#XA; }&#XA;&#XA; @越权#XA; public void onCancelled(DatabaseError databaseError){&#xA; Log.d(TAG,“错误:”,task.getException()); //不要忽视错误!&#xA; }&#xA;};&#xA; productsRef.addListenerForSingleValueEvent(valueEventListener);&#xA;  
&#xA;&#xA;

为了获得所有产品,你需要循环遍历 products 节点的所有子节点。因此,必须调用 child(“products”)

&#xA;&#xA;

如果您想要一个以上的随机产品,那么您可以创建一个循环并在 randomProductList 中添加任意数量的随机产品。

&#xA;&#xA;

这称为经典解决方案,您可以将其用于包含的节点只有少数记录,但如果您害怕获取大量数据,那么我会建议您使用第二种方法。这还需要通过添加名为 productIds 的新节点对数据库进行一些更改。您的数据库结构应如下所示:

&#xA;&#xA;
  Firebase-root&#xA; |&#XA; ---产品&#xA; | |&#XA; | --- productIdOne&#xA; | | |&#XA; | | --- //详情&#xA; | |&#XA; | --- productIdTwo&#xA; | |&#XA; | --- //详情&#xA; | &#XA; --- productIds&#xA; |&#XA; --- productIdOne:true&#xA; |&#XA; --- productIdTwo:true&#xA; |&#XA; --- //等等&#xA;  
&#xA;&#xA;

正如您在问题中提到的,如果您想避免下载整个产品节点包含具有所有属性的所有产品,您必须创建一个名为 productIds 的单独节点。因此,要获得单个产品,您只需要下载仅包含产品ID的简单节点。

&#xA;&#xA;

这种做法称为非规范化(复制数据),并且Firebase的常见做法。为了更好地理解,我重新命令您看到此视频,使用Firebase数据库进行非规范化是正常的

&#xA;&#xA;

但请记住,在这个新创建的节点中添加随机产品的方式,就像你需要在不再需要时删除它们一样。

&#xA;&#xA;

因此,要获取随机产品,您需要两次查询数据库。请参阅下面的代码:

&#xA;&#xA;
  DatabaseReference rootRef = FirebaseDatabase.getInstance()。getReference();&#xA; DatabaseReference productIdsRef = rootRef.child(“productIds “);&#xA; ValueEventListener valueEventListener = new ValueEventListener(){&#xA; @越权#XA; public void onDataChange(DataSnapshot dataSnapshot){&#xA;列表与LT;字符串&GT; productIdsList = new ArrayList&lt;&gt;();&#xA; for(DataSnapshot ds:dataSnapshot.getChildren()){&#xA; String productId = ds.getKey();&#xA; productIdsList.add(的productId);&#XA; }&#XA;&#XA; int productCount = productIdsList.size();&#xA; int randomNumber = new Random()。nextInt(productCount);&#xA;&#xA; DatabaseReference productIdRef = rootRef.child(“products”)。child(productIdsList.get(randomNumber));&#xA; ValueEventListener eventListener = new ValueEventListener(){&#xA; @越权#XA; public void onDataChange(DataSnapshot dataSnapshot){&#xA; String name = dataSnapshot.child(“name”)。getValue(String.class);&#xA; Log.d(“TAG”,名称);&#xA; }&#XA;&#XA; @越权#XA; public void onCancelled(DatabaseError databaseError){&#xA; Log.d(TAG,“错误:”,task.getException()); //不要忽视错误!&#xA; }&#XA; };&#XA; productIdRef.addListenerForSingleValueEvent(事件监听);&#XA; }&#XA;&#XA; @越权#XA; public void onCancelled(DatabaseError databaseError){&#xA; Log.d(TAG,“错误:”,task.getException()); //不要忽视错误!&#xA; }&#xA;};&#xA; productIdsRef.addListenerForSingleValueEvent(valueEventListener);&#xA;  
&#xA;&#xA;

当您对Firebase数据库执行查询时,可能会有多个结果。所以 dataSnapshot 包含这些结果的列表。即使只有一个结果, dataSnapshot 对象也会包含一个结果的列表。

&#xA;