Firebase查询可优化

Ski*_*ᴉʞS 5 android firebase firebase-realtime-database

我有一个Firebase Database看起来像:

我有一个名为的节点 Products

 Products
    |
    |--------prod1_id
    |         | 
    |         |--name : "prod1"
    |          --state: "free"
    |         
    |
    |---------prod2_id
              | 
              |--name : "prod2"
               --price: "not_free"
Run Code Online (Sandbox Code Playgroud)

然后我有用户的节点

Users
     |
     |--------user1_id
     |         | 
     |         |--name : "user1"
     |          --e-mail: "user1@email.com"
     |          
     |
     |---------user2_id
               | 
               |--name : "user2"
                --e-mail: "user2@email.com"
Run Code Online (Sandbox Code Playgroud)

在我的应用程序上,用户可以购买,只有当他/她这样做时,我才会创建一个新的节点PurchasedItems,在那里我存储了UserProduct

Purchased items
             |
             |--------user1_id
             |         | 
             |         |--prod1: "any_value"
             |          --prod2:  "any_value"
             |         
             |
             |---------user2_id
                       | 
                       |--prod1: "any_value"
Run Code Online (Sandbox Code Playgroud)

问题在于我对对象的查询,我这样做:

 products_ref= FirebaseDatabase.getInstance().getReference().child("products");
Run Code Online (Sandbox Code Playgroud)

问题是什么?

登录到应用程序的用户,即使他已经购买了产品,也会显示productNotFree布局,因为在产品上我没有提及用户购买此商品的内容,但我的"TryToPurchase"方法有类似之处,我有一个查询,PurchasedProducts以查看用户是否有此产品或不进行购买.

在我的onClick()方法中,我有这个来检查用户是否已经付款

root_ref.child("PurchasedProducts").child(currentuser).addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        if(dataSnapshot.hasChild(model.getProduct_id())){
            showToast("He has that product");
        }
        else{
            showToast("Purchasing");
            //Purchase for it

        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});
Run Code Online (Sandbox Code Playgroud)

到目前为止,我有这个switch()声明,setImageResource但从查询到products

注意:layoutFree例如是一个没有锁定的盒子,而layoutNotFree是同一个盒子但带锁

switch (model.getState()) {
        case "free":
            holder.card_image.setImageResource(layoutFree);
            break;
        case "not_free":
            holder.card_image.setImageResource(layoutNotFree));
            break;
        default:
            break;
    }
Run Code Online (Sandbox Code Playgroud)

现在我已经面临如果用户购买物品,即使他购买了物品,他/她也无法看到layoutFree,即使他/她已付款,他也会看到带锁的布局.

我曾经想过要做什么?

onBindViewHolder我有switch()声明的地方,我可以再Firebase询问是否currentUser有这个产品,如果他有这个产品,我把freeLayout放在NotFreeLayout上.

但我觉得它有点脏,所以我把它放在这里,看看是否还有另一种方法可以提高效率.

我想看到什么?

好吧,如果我是以支付一种产品的用户身份登录的,该产品的状态为"not_free",我希望看到产品的布局没有锁定项目,如果我支付一个项目,我创建一个表purchasedItems,我做这样的事情:

root_ref.child("PurchasedProducts").child(currentuser).child(productId).setValue("paid");
Run Code Online (Sandbox Code Playgroud)

而且我也希望看到RecyclerViewlayoutNotFree到layoutFree 的更改,是否可以通过任何方式进行更新而不是刷新Activity?刷新Activity意味着我必须重新做适配器,创建RecyclerView等...

我希望我已经正确地解释它并且一步一步地避免混淆,如果我在问题上做错了,可以随意编辑它或者向我提问并且我会编辑.

Moh*_*aby 3

在此示例中,所有产品表子项均保存在一个 ArrayList表中,仅对.Firebase Database

根据您的数据库架构。

首先,定义一个ArraylistofProducts.class来保存所有产品详细信息

 ArrayList<Products> productsArrayList = new ArrayList<>();
Run Code Online (Sandbox Code Playgroud)

二、定义Products.class新类中的

public class Products {

    public String  id;
    public String  name;
    public String state;

    public Products() {
    }

    public Products(String name, String state) {
        this.name = name;
        this.state = state;
    }

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getState() {
        return state;
    }


    public void setId(String id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setState(String state) {
        this.state = state;
    }

}
Run Code Online (Sandbox Code Playgroud)

我只添加id(位置搜索必需的),,namestate 可以添加其他值Products.class

第三,进行 Firebase 查询以获取所有产品子项

DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Products");
        ref.addListenerForSingleValueEvent(
                new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {


                        // for loop will be executed for each children
                        for(DataSnapshot userSnapshot : dataSnapshot.getChildren()){

                            // put snapShot in Products.class ...... only children added
                            // in This case Children Will be price, quantity
                            Products products = userSnapshot.getValue(Products.class);

                            // set id manually to tha same instance of the class
                            products.setId(userSnapshot.getKey());

                            // add the Post class to ArrayList
                            productsArrayList.add(products);
                        }

                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {
                        //handle databaseError
                    }
                });
Run Code Online (Sandbox Code Playgroud)

现在,在保存产品详细信息后,productsArrayList您可以在任何地方使用它们。

用于搜索ArrayList<Products>和获取特定内容的辅助方法position

 public int getArrayListProductsPosition(String id){

        for(int i = 0; i < productsArrayList.size() ; i++){

            // if the passed id equals some id in arrayList return arrayList position
            if(Objects.equals(productsArrayList.get(i).getId(), id)){
                return i;
            }

        }

        return 0;
    }
Run Code Online (Sandbox Code Playgroud)

第四,现在班级中的任何地方,如果您需要访问特定产品详细信息(UI例如更新);

    // pass the id of the product you want to get details about
    // I suppose this id will probably be retrived from another database tabel
    int position = getArrayListProductsPosition(id);

    //update your UI TextView quantity for example;
    String name = productsArrayList.get(position).getName()
    textQuantitiy.setText(name);

    // or update you UI ImageView for example;
Run Code Online (Sandbox Code Playgroud)

为了提高效率

-在搜索方法( getArrayListProductsPosition)中,将id's数据库中的产品保存为数字并更改为Products.class. String id因为Long id 比较比比String-String较慢Long-Long

--如果要更改产品表(不是静态的),请使用productsArrayList一次并在检索后立即进行查询(您不希望数据变旧)