我有一个 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
的新节点,我在其中存储 User
和 Product
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
.
根据您的数据库架构。
首先,定义一个Arraylist
的 Products.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 id
至 Long id
因为String-String
比较慢于 Long-Long
对比
-- 如果要更改 Products 表(不是静态的),请使用 productsArrayList
检索查询后立即执行一次(您不希望数据变旧)
关于android - Firebase 查询可优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48044561/