简体   繁体   中英

How to retrieve data from ValueEventListener Firebase

I have an Android app using Google Firebase.

I need to download an image with a random ID.

I have a function that must return a Bitmap of the random picture. In this function I read the amount of pictures from a separate database entry and then I generate a random ID in the range from 1 to the amount of pictures. Here is the code:

    Random rand = new Random();
    DatabaseReference amountRef = dbref.child("amount");
    amountRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            amount = dataSnapshot.getValue(Long.class);

        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
    long random = rand.nextLong() % amount + 1;

The function later downloads an image and produces and returns a bitmap. The problem is that the Listener code is executed parallel to the other code and the line

long random = rand.nextLong() % amount + 1;

produces a divide by zero error, because the amount variable is not yet updated. I also cannot put all the code inside OnDataChange, because I need to return the bitmap. Please tell me how to retrieve the data immediately or return the bitmap from inside the listener.

You have to use it like this

Random rand = new Random();
    DatabaseReference amountRef = dbref.child("amount");
    amountRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            amount = dataSnapshot.getValue(Long.class);
            // add Random rand = new Random(); here if you need new random objects everytime.
            long random = rand.nextLong() % amount + 1;
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

You are trying to access data from an asynchronous function, so if you try to access if after the variable, it might not have finished its work so it might return null, it is not sure and so you have to access it inside.

You cannot return something now that hasn't been loaded yet. With other words, you cannot simply use the amount object outside the onDataChange() method because it will always be null due the asynchronous behaviour of this method. This means that by the time you are trying to use that result outside that method, the data hasn't finished loading yet from the database and that's why is not accessible.

A quick solve for this problem would be to use those results only inside the onDataChange() method or if you want to use it outside, 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.

You can use a Text View with visibility=gone (so that its not visible in your activity).Use setText() to set value to it. After coming out of Value Event Listener, use getText() to get your value. Its just a trick which helps a lot. your code will look something like this:

 TextView textview=findViewById(R.id.textView);
Random rand = new Random();
    DatabaseReference amountRef = dbref.child("amount");
    amountRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            amount = dataSnapshot.getValue(Long.class);
textview.setText(""+amount);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
int amount=Integer.parseInt(textview.getText());
    long random = rand.nextLong() % amount + 1;

Hope this helps :)

Facing this challenge seriously, I still don't get a solution to it. I want to use the variable outside the onChangeMethod.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM