Ahmed Afifi
Ahmed Afifi

Reputation: 456

returning an object from an inner method

I am trying to build a separate class for firebase methods, one of these methods is to return an Object User

    public User getUser(){
        myRef.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                User user = dataSnapshot.child("users").child(mUserID).child("user_info").getValue(User.class);
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.d(TAG, "onCancelled: Error: " + databaseError.getMessage());
            }
        });
        return user;
    }

returning the user gives me an error. is it possible to return the User user from the inner onDataChange() method? and how?

Upvotes: 1

Views: 73

Answers (3)

OneCricketeer
OneCricketeer

Reputation: 191874

No, it's not possible because Firebase is asynchronous, and you're effectively trying to convert this method back into a blocking call by making the calling method "wait for" a returned object.

The appropriate pattern here is

1) make an interface.

public interface OnUserResult {
    void onUser(User u);
}

2) pass interface into void method
3) pass result back to Callback interface

public void getUser(final OnUserResult callback) {
    myRef.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            User user = dataSnapshot.child("users").child(mUserID).child("user_info").getValue(User.class);
           if (null!=callback) callback.onUser(user);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.d(TAG, "onCancelled: Error: " + databaseError.getMessage());
        }
    });
}

4) Rewrite the calling method to not expect a returned object

// Bad: User user = api.getUser();

// Good 
api.getUser(new OnUserResult() {
    @Override public void onUser(User u) {
         // Update the UI, or whatever 
        // Do not assign a global user variable here either 
    } 
});
// any external user variable will (usually) still be null here 

Libraries such as RxJava help you to implement this pattern in other ways

Upvotes: 3

wesmartin17
wesmartin17

Reputation: 55

Is user declared in the scope of the class? Because otherwise I don't know how getUser() is accessing the user it is returning. Try declaring user in getUser() instead of inside onDataChange because the user in onDataChange is only in the scope of that method.

Also, if onDataChange is never called, there is never a declared User and it would return null

Upvotes: 0

zXor
zXor

Reputation: 218

It is not possible to return anything from an inner class.. But one can initialize an instance variable inside the inner class , making it accessible to all members of the class

Upvotes: 1

Related Questions