简体   繁体   中英

Firebase Database for Android, trouble retrieving data

So I'm having trouble with retrieving data from my database. I think the problem lies in the return statement.

When I run the app the debug text where the flatID should be shown is blank. I know for sure that the data is on the database so that isn't the issue.

I'm still very new to Java and programming in general, thanks for your help and your patience :) The code is as follows.

flatID = readFlatID();
debug1.setText(flatID);

    public String readFlatID(){

    String uid = mAuth.getCurrentUser().getUid().toString();

    mDatabase.child("Users").child(uid).child("Flat")
            .addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            flat = dataSnapshot.getValue().toString();
            Toast.makeText(getApplicationContext(),"Data Read Successfully",Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

    return flat;


}

Firebase methods are Asynchronous. That's why the text was not set. You can set up a listener and pass that to the method such that you get a callback when the data is fetched. Here is what I mean code-wise:

//Create an interface
    interface IDatabaseLoad {
        void onDataLoadSuccess(String data);
        void onDataLoadFailed();
    }

//Initialize it
IDatabaseLoad databaseLoad = new IDatabaseLoad() {
        @Override
        public void onDataLoadSuccess(String data) {
            debug1.setText(data);
            Toast.makeText(getApplicationContext(),"Data Read Successfully",Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onDataLoadFailed() {

        }
    };

//modify your method
public void readFlatID(final IDatabaseLoad listener){

    String uid = mAuth.getCurrentUser().getUid().toString();

    mDatabase.child("Users").child(uid).child("Flat")
            .addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    listener.onDataLoadSuccess(dataSnapshot.getValue().toString());
                }

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

Now you just need to call readFlatID(databaseLoad) and the TextView will be set with the data after it gets fetched.

As fetching data from Firebase server is performed on the background thread on mobile devices, it takes time for the app to actually load the whole data. That is why return flat; will return nothing at the time the code is executed.

The simplest solution for you is, you have to put all what you want to do with the retrieved data inside the onDataChange() method. You can do something like this:

 public void readFlatID() {

        String uid = mAuth.getCurrentUser().getUid().toString();

        mDatabase.child("Users").child(uid).child("Flat")
                .addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        flat = dataSnapshot.getValue().toString();
                        debug1.setText(flat);
                        Toast.makeText(getApplicationContext(), "Data Read Successfully", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {

                    }
                });

    }

You cannot return something now that hasn't been loaded yet. The onDataChange() method has an asynchronous behaviour which means that is called even before you are trying to get the flat object from the database. That's why it is always null outside onDataChange() method. With other words, by the time you are returning the flat object, the data has not finished loading yet from the database, so a quick solve for this would be to use the value only inside the onDataChange() method or if you want to use it outside, dive into the asynchronous world and create your own callback as explained in the last part of my answer from this post .

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