Firebase Optimized Request

I have a Firebase Database that looks like this:

I have a node named Products

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

Then I have node for users

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

And in my application, the user can buy, and only when he / she does, I create a new node called PurchasedItems , where I store User and Product

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

The thing is, in my query for objects, I do this:

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

WHAT A PROBLEM?

The user who entered the application, even if he bought the product, he will show the productNotFree layout, because on the products I do not have a link to the user who bought this product, but I have something similar to my "TryToPurchase", because that I have a request to PurchasedProducts to find out if the user has this product or not, to make a purchase or not.

In my onClick() method, I have this to check if the user has paid for it or not.

 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) { } }); 

So far I have had a switch() on setImageResource , but from a request in Products

NOTE: layoutFree is, for example, a field in which there is no lock, and layoutNotFree is the same field, but with a lock

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

Now I am faced with the fact that if the user buys the goods, he / she will not be able to see the layout, even if he buys it, he will see the layout with a lock, even if he paid for it.

What did I think to do?

In the same onBindViewHolder , where I have a switch() , I could make another Firebase request, asking if currentUser this product, and if it has this product, I put freeLayout otherwise NotFreeLayout.

But I think this is a little dirty, so I put it here to see if there is another way to make it effective.

What would I like to see?

Well, if I am registered as a user who paid for one product with the status "not_free", I would like to see a product with a layout without a blocking element, and also, if I pay for an element, I create a table PurchasedItems and I do something like this:

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

And also I would like RecyclerView change layoutNotFree to layoutFree, is this some way to do this, instead of updating the Activity ? Updating Activity means I need to re-do the adapter, create a RecyclerView , etc.

I hope I explained this correctly and step by step to avoid confusion, if I did something wrong to the question, feel free to edit it or ask me about it, and I will edit it.

+5
source share
2 answers

In this example, all child product tables are stored in one ArrayList with only one query to the Firebase Database .

According to your database schema.

First, Define an ArrayList of Products.class to store all product details

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

Second, define Products.class in a new 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; } } 

I add only id (necessary to search for a position), name , state You can add other values ​​to Products.class

Third, make a Firebase request to get all products

 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 } }); 

Now that product information is stored in productsArrayList , you can use it anywhere.

Helper method to search in ArrayList<Products> and get specific 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; } 

Fourth, Now, if a class is needed, if you need to access specific product information, for example, update the 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; 

For greater efficiency

- in the search method ( getArrayListProductsPosition ), save id's products in the database as numbers and change the value in Products.class . String id to Long id because String-String comparison is slower than Long-Long comparison

- if the product table needs to be changed (not static), use productsArrayList once and immediately after receiving the request (you do not want the data to be old)

+3
source

To make sure the code is optimized, you can use a shared preference to save the acquired identifier for the user. Access to the database may cause a delay in the program flow. Using a data snapshot returns the product identifier and stores it in a shared preference variable and check the product identifier when accessing the product details to show a free layout. You can also save the acquired information in a child of the user to get a more specific content search.

0
source

Source: https://habr.com/ru/post/1274416/


All Articles