this.books = new ArrayList<>();
mFirebaseDatabaseReference.child(SellBooksPost).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange( DataSnapshot AdataSnapshot) {
for (final DataSnapshot AmessageSnapshot : AdataSnapshot.getChildren()) {
bFirebaseDatabaseReference.child(mUserId).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot BdataSnapshot) {
for (DataSnapshot BmessageSnapshot : BdataSnapshot.getChildren()) {
if (BmessageSnapshot.child("book").getValue().toString().equals(AmessageSnapshot.child("SellBooksPostId").getValue().toString())){
Log.d("INFO", "SELL BOOK book " + BmessageSnapshot.child("book").getValue());
Log.d("INFO", "SELL BOOK DETAIL " + AmessageSnapshot.child("SellBooksPostId").getValue());
books.add(new Book(
AmessageSnapshot.child("SellBooksPostId").getValue().toString(),
AmessageSnapshot.child("bookTitle").getValue().toString()
));
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
saleBookPostAdapter = new SaleBookPostAdapter(getApplicationContext(), books);
mRoomRecyclerView.setHasFixedSize(true);
mRoomRecyclerView.setAdapter(saleBookPostAdapter);
It's hard to say if this is a problem, but I do not see a call to RecyclerView.Adapter#notifyDataSetChanged() method after updating the data. So try call
salesBookAdapter.notifyDataSetChanged()
after
books.add(new Book(
AmessageSnapshot.child("SellBooksPostId").getValue().toString(),
AmessageSnapshot.child("bookTitle").getValue().toString()
));
Related
This question already has answers here:
How to save users score in firebase and retrieve it in real-time in Android studio
(3 answers)
Closed 2 years ago.
I am trying to make an application on Android, I am a beginner.
I try to increment the "stock" of a product, but my following code is not reliable. I had connection problems on the device and the "stock" did not increase correctly. How can I execute it as a transaction?. I cannot find extensive documentation.
final HashMap<String, BigDecimal> detalle = new HashMap<String, BigDecimal>();
Query query = mDatabase.child("COMPRAS").child(key).child("COMPRASPRODUCTO");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()){
CompraProducto producto = ds.getValue(CompraProducto.class);
detalle.put(producto.getId(),new BigDecimal(producto.getCantidad()));
}
for (String key : detalle.keySet()) {
Query queryp = mDatabase.child("PRODUCTO").child(key);
queryp.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot data) {
Producto p = data.getValue(Producto.class);
try{
stockOriginal = new BigDecimal(p.getStock());
mProductoProvider = new productoProvider();
mProductoProvider.refreshStock(p.getCodigo(), stockOriginal.add(detalle.get(p.getCodigo())).toString()).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
}
});
}catch(Exception e){
Toast.makeText(comprarProducto.this, "Producto " + data.getKey() + " no existe.", Toast.LENGTH_LONG).show();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
Thank you.
I am using updateChildren and ServerValue.increment
Using these paths, you can perform simultaneous updates to multiple locations in the JSON tree with a single call to updateChildren(), such as how this example creates the new post in both locations. Simultaneous updates made this way are atomic: either all updates succeed or all updates fail.
final Map<String, Object> productUpdates = new HashMap<>();
Query query = mDatabase.child("COMPRAS").child(key).child("COMPRASPRODUCTO");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()){
System.out.println("---" + ds.getKey());
CompraProducto producto = ds.getValue(CompraProducto.class);
productUpdates.put("/PRODUCTO/" + ds.getKey() +"/stock", ServerValue.increment(producto.getCantidad()));
}
System.out.println("==============");
if(!productUpdates.isEmpty()) {
mDatabase.updateChildren(productUpdates, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError == null) {
mCompraProvider.actualizar(key, inputProveedor.getText().toString(), inputFecha.getText().toString(), "PENDIENTE").addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(comprarProducto.this, "Compra del proveedor " + inputProveedor.getText().toString() + " guardada correctamente.", Toast.LENGTH_SHORT).show();
}
});
System.out.println("onComplete: success");
} else {
System.out.println("onComplete: fail" + databaseError.toException());
}
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
I have an app which has a structure like
Chatrooms--------
Messages-------
Chatroomid---------
-Message1
-Message2
In this chatroom when the number of messages reaches 200 I want to delete the first 50 messages.So if the messages are 200 it will delete the messages from message1 to message50.I am using a push key for the messages.
My java code for sending message
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Map<String,Object> message = new HashMap<>();
message.put("message",messageBox.getText().toString());
message.put("imageurl",ppurl);
message.put("sender",FirebaseAuth.getInstance().getCurrentUser().getUid());
reference2.push().setValue(message).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
messageBox.setText("");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(chatroom.this, "Error" + e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
});
My java code for retrieving message
private void getdata() {
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
for (DataSnapshot npsnapshot : snapshot.getChildren()) {
message l = npsnapshot.getValue(message.class);
list.add(l);
}
messageAdapter.notifyDataSetChanged();
}else {
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
You can easily add this in your existing getdata function:
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
if (snapshot.getChildrenCount() > 200) {
int count = 0;
Map<String, Object> updates = new HashMap<>();
for (DataSnapshot npsnapshot : snapshot.getChildren()) {
if (count++ <= 50) {
updates.put(npsnapshot.getKey(), null);
}
}
ref.updateChildren(updates); // this will refire onDataChange, so we'll update the UI then
}
else {
for (DataSnapshot npsnapshot : snapshot.getChildren()) {
message l = npsnapshot.getValue(message.class);
list.add(l);
}
messageAdapter.notifyDataSetChanged();
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
throw error.toException(); // don't ignore errors
}
});
There is also a Cloud Functions sample that can do this server-side for you btw: https://github.com/firebase/functions-samples/tree/master/limit-children
Hi I want to read the display data from RecyclerView and make comparison.
This my layout for the activity:
What I want to do is to read all data from RecyclerView and compare with Daily Calorie Suggestion.
After reading all data, I need to make comparisons on how many times the user have taken above, less or sufficient total calories as shown in the "Analysis of Total Calories Consumed of Last 7 Days"
The code:
#Override
protected void onStart() {
Query query = ref.orderByChild("timeStamp").limitToLast(7).endAt(Date);
super.onStart();
if (query != null) {
query .addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
userHighlights = new ArrayList<>();
for (DataSnapshot ds : dataSnapshot.getChildren()) {
userHighlights.add(ds.getValue(HighightsModel.class));
requiredCalorieRef = FirebaseDatabase.getInstance().getReference("Users").child(FirebaseAuth.getInstance().getCurrentUser().getUid());
requiredCalorieRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String userCalorieSuggestion = String.valueOf((dataSnapshot.child("daily calorie").getValue()));
int daily_calorie = Integer.parseInt(userCalorieSuggestion);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
HighlightsAdapter highlightsAdapter = new HighlightsAdapter(userHighlights);
highlightsRV.setAdapter(highlightsAdapter);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(UserNewHighlights.this, databaseError.getMessage(),
Toast.LENGTH_SHORT).show();
}
});
}
}
This is my firebase:
Do I have to write a new code to solve this problem or else? Any help will be much appreciated. Thanks
As #MasoudDarzi mentioned, it's not related to the RecyclerView.
You can try something like this:
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
userHighlights = new ArrayList<>();
for (DataSnapshot ds : dataSnapshot.getChildren()) {
userHighlights.add(ds.getValue(HighightsModel.class));
requiredCalorieRef = FirebaseDatabase.getInstance().getReference("Users").child(FirebaseAuth.getInstance().getCurrentUser().getUid());
requiredCalorieRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String userCalorieSuggestion = String.valueOf((dataSnapshot.child("daily calorie").getValue()));
int daily_calorie = Integer.parseInt(userCalorieSuggestion);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
HighlightsAdapter highlightsAdapter = new HighlightsAdapter(userHighlights);
highlightsRV.setAdapter(highlightsAdapter);
// do calculation here with userHighlights
int countExceeded = 0, countBelow = 0, countSufficient = 0;
for (HighightsModel h : userHighlights) {
if (h.totalCalorie > daily_calorie) {
countExceeded++;
} else if (h.totalCalorie < daily_calorie) {
countBelow++;
} else {
countSufficient++;
}
}
// update your TextView with the count numbers
// todo
}
}
so The brute force solution is to have a for in your data after getting the 7 days average.
for (your 7 days data){
// check if your data is lower or higher than the average
// and store number of higher or lower
}
looking for a better solution?
I have solved my problem by adding another child at History node. Whereby, previously I have only these for History :
but I add new child which is called STATUS, the status is updated from previous activity as seen the pic below:
so what I did for the code is :
private void upDateAnalysisAbove() {
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("History");
DatabaseReference mRef = ref.child(FirebaseAuth.getInstance().getCurrentUser().getUid());
Query mQuery = mRef.orderByChild("status").equalTo("ABOVE").limitToLast(7);
mQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = String.valueOf(dataSnapshot.getChildrenCount());
int values = Integer.parseInt(value);
txt_above_output.setText(values + " times(s)");
upDateAnalysisLess(values);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
//LESS
private void upDateAnalysisLess(int values) {
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("History");
DatabaseReference mRef = ref.child(FirebaseAuth.getInstance().getCurrentUser().getUid());
Query mQuery = mRef.orderByChild("status").equalTo("LESS").limitToFirst(7);
mQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String valueLess = String.valueOf(dataSnapshot.getChildrenCount());
int values_Less = Integer.parseInt(valueLess);
if (values_Less == 0){
txt_less_output.setText(values_Less + " times(s)");
}
if (values > values_Less){
int finalCount = values - values_Less ;
txt_less_output.setText(finalCount + " times(s)");
}
if (values <values_Less){
int finalCount = values_Less - values ;
txt_less_output.setText(finalCount + " times(s)");
}
updateSuff();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
//SUFFICIENT
private void updateSuff() {
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("History");
DatabaseReference mRef = ref.child(FirebaseAuth.getInstance().getCurrentUser().getUid());
Query mQuery = mRef.orderByChild("status").equalTo("SUFFICIENT").limitToFirst(7);
mQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = String.valueOf(dataSnapshot.getChildrenCount());
int suffValue = Integer.parseInt(value);
if (suffValue == 0) {
txt_sufficient_output.setText(suffValue + " times(s)");
}
if (suffValue != 0){
txt_sufficient_output.setText(suffValue + " times(s)");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Here is the output:
credit to this post that helped me a lot, and thanks for those who tried to help me.
Here is my db format:
{
"classes": {
"class1": {
"name":"C1"
},
"class2": {
"name":"C2"
}
},
"students": {
"student1": {
"name":"S1"
},
"student2": {
"name":"S2"
}
},
"classes_enrollments": {
"class1": {
"student1": true,
"student2": true
},
"class2": {
"student1": true
}
},
"students_enrollments": {
"student1": {
"class1": true,
"class2": true
},
"student2": {
"class1": true
}
}
}
I want to get data like : class1 named C1, has 2 students S1 and S2
I tried this way
database.child("classes_enrolments").addValueEventListener(eventListener);
but the output is just the data of classes_enrolments node: {class2={student1=true}, class1={student2=true, student1=true}}
How to achieve it, please?
Thank you
To solve this, please use the cpde below:
String class1 = "class1";
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference nameRef = rootRef.child("classes").child(class1).child("name");
ValueEventListener nameValueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot nameDataSnapshot) {
String className = nameDataSnapshot.getValue(String.class);
Log.d(TAG, class1 + " named " + className);
DatabaseReference class1Ref = rootRef.child("classes_enrollments").child(class1);
ValueEventListener class1EventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
long numberOfStudent = dataSnapshot.getChildrenCount();
Log.d(TAG, "has " + numberOfStudent + " students");
for(DataSnapshot studentDataSnapshot : dataSnapshot.getChildren()) {
String student = studentDataSnapshot.getKey();
DatabaseReference studentsRef = rootRef.child("students");
DatabaseReference studentRef = studentsRef.child(student);
ValueEventListener studentsValueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String name = ds.child("name").getValue(String.class);
Log.d(TAG, name);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
studentRef.addListenerForSingleValueEvent(studentsValueEventListener);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
class1Ref.addListenerForSingleValueEvent(class1EventListener);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
nameRef.addListenerForSingleValueEvent(nameValueEventListener);
In order to solve this, you should first get the name of the class, the query to get the number of student and in the end to get the name of the students. The result in the logcat will be:
class1 named C1
has 2 students
S1
S2
I have an if and else block. if it conforms to the if condition, it will list the data in the database as imageAdapter. anasayfaAdapter will be used if elsee comes into it.
if(kisiIdd.equals(userId))
{
adapterr = new imageAdapter(getActivity(), kullaniciList);
recyclerView.setAdapter(adapterr);
adapterr.setOnItemClickListener(urunlerimFragment.this);
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
kullaniciList.clear();
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
Kullanici kullaniciModel = postSnapshot.getValue(Kullanici.class);
String id=kullaniciModel.getKisiId().toString();
kullaniciList.add(kullaniciModel);
kullaniciModel.setKey(postSnapshot.getKey());
}
adapterr.notifyDataSetChanged();
progressCircle.setVisibility(View.INVISIBLE);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(getActivity(), databaseError.getMessage(), Toast.LENGTH_SHORT).show();
progressCircle.setVisibility(View.INVISIBLE);
}
});
}
else
{
anasayfaAdapter = new anasayfaAdapter(getActivity(), kullaniciList);
recyclerView.setAdapter(anasayfaAdapter);
anasayfaAdapter.setOnItemClickListener(urunlerimFragment.this);
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
kullaniciList.clear();
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
Kullanici kullaniciModel = postSnapshot.getValue(Kullanici.class);
String id=kullaniciModel.getKisiId().toString();
kullaniciList.add(kullaniciModel);
kullaniciModel.setKey(postSnapshot.getKey());
}
anasayfaAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(getActivity(), databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
if the data in the database from the database if the imageAdapter to use to list. In the Else block, it will use the anasayfaAdapter adapter. Why would an algorithm fit?
but it does not happen. How do you have a suggestion?