android - Firebase 查询可优化

标签 android firebase firebase-realtime-database

我有一个 Firebase 数据库,它看起来像:

我有一个名为 Products 的节点

 Products
    |
    |--------prod1_id
    |         | 
    |         |--name : "prod1"
    |          --state: "free"
    |         
    |
    |---------prod2_id
              | 
              |--name : "prod2"
               --price: "not_free"

然后我有用户的节点

Users
     |
     |--------user1_id
     |         | 
     |         |--name : "user1"
     |          --e-mail: "user1@email.com"
     |          
     |
     |---------user2_id
               | 
               |--name : "user2"
                --e-mail: "user2@email.com"

在我的应用程序中,用户可以购买,只有当他/她购买时,我才会创建一个名为 PurchasedItems 的新节点,我在其中存储 UserProduct

Purchased items
             |
             |--------user1_id
             |         | 
             |         |--prod1: "any_value"
             |          --prod2:  "any_value"
             |         
             |
             |---------user2_id
                       | 
                       |--prod1: "any_value"

问题是在我查询对象时,我这样做了:

 products_ref= FirebaseDatabase.getInstance().getReference().child("products");

问题是什么?

登录到该应用程序的用户,即使他购买了产品,它也会显示 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) {

    }
});

到目前为止,我对 setImageResource 有这个 switch() 语句,但是从查询到 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;
    }

现在我遇到了如果用户购买一个项目,他/她将无法看到布局免费即使他购买了它,他/她即使他/她已经付费也会看到带锁的布局.

我想做什么?

在相同的 onBindViewHolder 上,我有 switch() 语句,我可以对 Firebase 进行另一个查询,询问 currentUser 有这个产品,如果他有那个产品,我就放 freeLayout,否则放 NotFreeLayout。

但我觉得它有点脏,所以我把它放在这里看看是否有其他方法可以使其高效。

我想看到什么?

好吧,如果我作为一个用户登录并购买了一个状态为“not_free”的产品,我希望看到该产品的布局没有锁定项目,而且如果我支付了一个项目,我会创建一个表 purchasedItems 我做了这样的事情:

root_ref.child("PurchasedProducts").child(currentuser).child(productId).setValue("paid");

而且我还想看到 RecyclerView 将 layoutNotFree 更改为 layoutFree,有什么方法可以代替刷新 Activity?刷新 Activity 意味着我必须重新做适配器,创建 RecyclerView 等...

我希望我已经正确并逐步地解释了它以避免混淆,如果我在问题上做错了什么,请随时编辑它或向我提问,我会进行编辑。

最佳答案

在这个例子中,所有产品表的 child 被保存在one ArrayList 只有一个请求Firebase Database .

根据您的数据库架构。

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

 ArrayList<Products> productsArrayList = new ArrayList<>();

其次,定义 Products.class在新类(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;
    }

}

我只加id (位置搜索所必需),name , state 您可以将其他值添加到 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
                    }
                });

现在,产品详细信息保存在 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;
    }

第四,现在任何地方的类如果你需要访问特定的产品细节,更新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;

为了提高效率

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

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

关于android - Firebase 查询可优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48044561/

相关文章:

java - 崩溃 : com. badlogic.gdx.physics.box2d.World.jniCreateBody

typescript - 火力地堡功能 : Unhandled error RangeError: Maximum call stack size exceeded

javascript - 火力地堡 : First Argument contains undefined in property

android - Firebase 数据库快速入门处理计数的方式是否安全?

java - Android 中的单例与应用程序上下文?

android - 在android中以pdf格式显示sqlite数据库内容

javascript - onAuthStateChanged 更改 Firebase 3.0.0 后引用不会重新运行

javascript - 更改 Firebase 中元素的路径

安卓游戏效果

firebase - 存档的动态链接在哪里?