How to make addListenerForSingleValueEvent to work in loop?

Tags: , , , ,



I’m trying to access the addListenerForSingleValueEvent for a specific number of times based on the amount of item’s present in cart but since it listen’s for only one time I’m unable to fetch the information from the database (i.e. I need to fetch available of each product but it’s only fetching only once and applying same available value for rest of the item’s present in cart)

private void updateAdminView(List listOfItems) {

    final DatabaseReference cartListRef = FirebaseDatabase.getInstance().getReference().child("Cart List");
    final DatabaseReference orderListRef = FirebaseDatabase.getInstance().getReference().child("Order List");

    for(Cart cartItem : listOfItems)
    {
        final HashMap<String,Object> cartMap = new HashMap<>();
        cartMap.put("pid",cartItem.getPid());
        cartMap.put("name",cartItem.getName());
        cartMap.put("price",cartItem.getPrice());
        cartMap.put("weight",cartItem.getWeight());
        cartMap.put("date",cartItem.getDate());
        cartMap.put("quantity",cartItem.getQuantity());
        cartMap.put("sid",cartItem.getSid());
        cartMap.put("description",cartItem.getDescription());
        cartMap.put("duration",cartItem.getDuration());
        cartMap.put("time",cartItem.getTime());
        cartMap.put("usage",cartItem.getUsage());

        cartListRef.child("Admin View").child(Prevalent.currentOnlineUser.getPhone())
                .child(cartItem.getPid()).updateChildren(cartMap).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                Toast.makeText(ConfirmFinalOrderActivity.this, "You can purchase more products once your order is verified", Toast.LENGTH_SHORT).show();
            }
        });

        orderListRef.child("Admin View").child(Prevalent.currentOnlineUser.getPhone())
                .child(cartItem.getPid()).updateChildren(cartMap);

        final String dQuantity = cartItem.getQuantity();
        final String pid = cartItem.getPid();

        final DatabaseReference reference = FirebaseDatabase.getInstance().getReference().child("Products").child(pid);
        reference.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                sAvailable = Objects.requireNonNull(dataSnapshot.child("available").getValue()).toString();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        int quan = Integer.parseInt(dQuantity);
        int Ava = Integer.parseInt(sAvailable);
        int k = Ava - quan;
        String d = String.valueOf(k);
        reference.child("available").setValue(d).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                Toast.makeText(ConfirmFinalOrderActivity.this, "Done..!", Toast.LENGTH_SHORT).show();
            }
        });


    }


}

The value of sAvailable is as same as the first cart item. It’s not changing its value though it’s in for loop. I want to fetch sAvailable value for all cart items.

Answer

firebase database read write operate is asynchronous, which means you cannot get the result immediately´╝îyou code is error prone, try another way

using one transaction to batch update all, asynchronous to sync consider using this pattern

    // outside callback
    CountDownLatch countDownLatch = new CountDownLatch(1);

    // in callback
    countDownLatch.countDown();

    // outside callback
    countDownLatch.await();

    // callback is invoked. do anything you want


Source: stackoverflow