androidfirebasefirebase-realtime-database

How do I read an object in from Firebase?


I'm trying to get to grips with Firebase, and just can't get this to work!

So, my Activity needs to show a Chart object from the database. Chart is defined in a separate class. In the OnCreate method, I do the following:

    Intent intent = getIntent();
    chartKey = intent.getStringExtra("ChartKey");
    chart = new Chart(chartKey);
    chart.initialiseChart();
    chartName.setText(chart.getName());

So, I read in the chart key which has been passed through from the previous activity. I use that to create a new Chart object. Then I need to use that key to read the Chart object in from the database and set up the rest of the object (which is what I'm trying to do in initialiseChart), and then retrieve the Chart name and display it.

However, I can't get it to work properly - initialiseChart is returning a Chart with just the key set (so the same as when it was passed in).

Here are the relevant parts of my Chart class:

    public class Chart {
        private String uid, key, name, details;
    
        public Chart() {}
        public Chart(String chartKey) {
            this.key = chartKey;
        }
    
       @Exclude
        public Map<String, Object> toMap() {
            HashMap<String, Object> result = new HashMap<>();
            result.put("uid", uid);
            result.put("key", key);
            result.put("name", name);
            result.put("details", details);
            return result;
        }
    
        public String getKey() { return this.key; }
        public String getUid() { return this.uid; }
        public String getName() { return this.name; }
        public String getDetails() { return this.details;}

public void initialiseChart() {

    if(this.key == null) return;

    DatabaseReference mChartReference = FirebaseDatabase.getInstance().getReference()
            .child("charts").child(this.key);

    mChartReference.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            Chart chart = dataSnapshot.getValue(Chart.class);
            setUpChart(chart);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    });
}

private void setUpChart(Chart chart) {
    this.uid = chart.uid;
    this.name = chart.name;
    this.details = chart.details;
}

As I say, the problem is that, after calling 'initialiseChart' from the Activity, the chart still isn't set up. I'm guessing that maybe it's carrying on to this line before it's retrieved the data from the database? So presumably I need to allow for some kind of Async task or... something?

I am seeking the proper way to do this. I'm just going round in circles with it, and getting myself confused. I'm also relatively new to Java. I know this is probably a very basic thing to do, but I've been through the documentation and as many examples as I can find, and can't see anything that does this.


Solution

  • The reason this does not work is that addListenerForSingleValueEvent is Asynchronies process. When this code runs:

    Intent intent = getIntent();
    chartKey = intent.getStringExtra("ChartKey");
    chart = new Chart(chartKey);
    chart.initialiseChart();
    chartName.setText(chart.getName()); // here the data isn't ready yet.
    

    chartName.setText(chart.getName()); -> the object chart does not have the data ready for use. What you might do is to add listener:

     Intent intent = getIntent();
    chartKey = intent.getStringExtra("ChartKey");
    chart = new Chart(chartKey);
    chart.initialiseChart(new Runnable{
       public void run(){
           chartName.setText(chart.getName()); // this should run on ui thread         
       }
    });