Synchronization problem while getting data from firebase database

muratcangm :

I have a problem with my Firebase database data retrieve sync. I am able to get data but return works before it. So my data never put in the intended list.

Here is my code:

DatabaseManager databaseManager = new DatabaseManager();
MedicineData medicineData = new MedicineData();
boolean validated = false;
private static final String TAG = "BarcodeDecoderDataMatrix";

public Map getDataMatrix(String dataMatrixText) {

    Map<String, Object> dataMatrix = new HashMap<>();
    String barcodeNum = getBarcodeNumber(dataMatrixText);
    String expireDate = getExpireDate(dataMatrixText);
    String serialNum = getSerialNumber(dataMatrixText);
    String partyNum = getPartyNumber(dataMatrixText);

    dataMatrix.put("barcodeNumber",barcodeNum);
    dataMatrix.put("expireDate", expireDate);
    dataMatrix.put("serialNumber", serialNum);
    dataMatrix.put("partyNumber", partyNum);

    getMedicineName(barcodeNum, (success) -> {
        if(success){
            //find the data on database
            dataMatrix.put("medicineName", medicineData.getProductName());
            dataMatrix.put("companyName", medicineData.getCompanyName());
            dataMatrix.put("price", medicineData.getPrice());
        }
        else {
            //can't find on database
        }
    });

    return dataMatrix;
}

This method called from another class to get dataMatrix list.

    private void getMedicineName(String barcodeNum, SimpleCallback<Boolean> finishedCallback) {

      DatabaseReference rootRef = databaseManager.getReference();
      DatabaseReference medicinesRef = rootRef.child("MedicineList");
      Query queryMedicineNameFinder = medicinesRef.orderByKey().equalTo(barcodeNum);
      ValueEventListener valueEventListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            for(DataSnapshot ds : dataSnapshot.getChildren()) {
                medicineData = ds.getValue(MedicineData.class);
            }

            if (medicineData != null){
                validated = true;
            }
            finishedCallback.run(validated);
        }
        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
            finishedCallback.run(false);
        }
    };
    queryMedicineNameFinder.addListenerForSingleValueEvent(valueEventListener);
}

These two methods are in the same class called BarcodeDecoderDataMatrix. I create an instance of this class from another class and call getDataMatrix method. I am expecting to get a list include my values. I can get barcodeNum, expireDate, serialNum, partyNum values without a problem. But the list doesn't include medicineName, companyName and price informations. I made a debug so I know I can get data from database. I can see it in medicineData variable. I am pretty sure it is a sync issue. Because my data in medicineData but it can't put it in the list before return called.

How can I make this happen?

Alex Mamo :

addListenerForSingleValueEvent() method that you are using in your code, is asynchronous. This means that it returns immediately, while onDataChange() method fires only when the results are available.

What you are doing in your code is incorrect because you assuming that the results are immediately available and are not.

When you call getMedicineName() method, you should directly use dataMatrix in the callback, after the data is known that is available.

For more information, I recommend you see the last part of my anwser from this post in which I have explained how it can be done using a custom callback. You can also take a look at this video for a better understanding.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=195241&siteId=1
Recommended