0

I am a newbie in android studio. I want to know how many times "plastic" appears in the Firebase Document field. And show it in MPChart. I count 'Plastic' in Firebase Connect, but it can't work in data().How can I write Plastic?

public class MainChart {
BarChart barChart;
int Plastic;
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.chart);
    getMultipleDocs();
    BarData barData = new BarData();
    barData.addDataSet(barDataSet);
    barChart.setData(barData);
    barChart.invalidate();
}
public void getMultipleDocs() {
            .collection("Garbage")
            .whereEqualTo("name","plastic")
            .get()
            .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
                @Override
                public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                        List<DocumentSnapshot> snapshotList = queryDocumentSnapshots.getDocuments();
                        for(DocumentSnapshot snapshot:snapshotList){
                            Log.d(TAG, "onSuccess: "+snapshot.getData().toString());
                        }
                        Plastic++;
                        Log.d(getClass().getName(), "plastic have = " + Plastic);
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.e(TAG, "onFailure: ", e);
                    }
                });
public ArrayList<BarEntry> data(){
    ArrayList<BarEntry> dataVal = new ArrayList<>();
    dataVal.add(new BarEntry(0,Plastic));
    return dataVal;
}

}

My getMultipleDocs() code

My data() code

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Jun JIe
  • 3
  • 2

1 Answers1

0

Data is loaded from Firestore (and most modern cloud APIs) asynchronously, since it may take some time. While the data is being loaded your main code continues to execute. Then when the data is available, your onSuccess gets called.

The result of this is that your dataVal.add(new BarEntry(0,Plastic)) runs before Plastic++ ever gets called. You can most easily validate that by running the code in a debugger and setting breakpoints, or with some well places log statements.

The solution is always the same: any code that needs the data from Firestore needs to be inside onSuccess or be called from there. So:

...
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
    @Override
    public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
            List<DocumentSnapshot> snapshotList = queryDocumentSnapshots.getDocuments();
            for(DocumentSnapshot snapshot:snapshotList){
                Log.d(TAG, "onSuccess: "+snapshot.getData().toString());
            }
            Plastic++;

            Log.d(getClass().getName(), "plastic have = " + Plastic);
            public ArrayList<BarEntry> data(){
                ArrayList<BarEntry> dataVal = new ArrayList<>();
                dataVal.add(new BarEntry(0,Plastic));
                return dataVal;
            }
        }
    })
    .addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            Log.e(TAG, "onFailure: ", e);
        }
    });

For more on this see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • However I got an error in "return dataVal". "Cannot return a value from a method with void result type" – Jun JIe Nov 10 '21 at 20:21
  • Oh yeah, that definitely won't work. I just copied your code into there to show where it needs to be, but you'll need to make more changes. Key is that any code that needs the data from Firestore needs to be inside `onSuccess` or be called from there. You can't `return` it from there, as nobody is waiting for that return value anymore. – Frank van Puffelen Nov 11 '21 at 00:00
  • Ok! I got it! Thanks for your help! – Jun JIe Nov 11 '21 at 01:38
  • Hi,I am sorry because I am a newbie in android studio.Now, I know the code need to be inside onSuccess and can’t return it from there. How can write that “Plastic” can be placed in MPChart.Do I need to learn more in Java ArrayList? Is there any information that I can refer to? Thanks a lot... – Jun JIe Nov 11 '21 at 10:50
  • After you call `dataVal.add(new BarEntry(0,Plastic));`, you should call code to update the chart. See the link I provided at the bottom of my answer for more examples of this. – Frank van Puffelen Nov 11 '21 at 15:23
  • I can't thank you enough! – Jun JIe Nov 11 '21 at 15:53