Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I implement an Observer to get data from a listener?

I am using the MaterialDrawer library to create a simple drawer for my app, some of the instances of classes in the library need a string passed into them when called. An example is the IProfile class:

IProfile profile = new ProfileDrawerItem().withName("John Doe");

where the withName() method takes in a string.

I have created a class MyObservable.java (extends Observable) class that I intend using to get data to be used in my MainActivity which has the MaterialDrawer library implemented. In this class, I have a method implementData() which has my listener for what I need from my firebase database.

This is what it looks like:

    public class MyObservable extends Observable {

    // Attach our firebase reference...
    Firebase userRef = new Firebase("https://myApp.firebaseio.com/users");
    AuthData authData;

    public String username = "";
    public String email = "";


    public void changeUsername(String username) {
        this.username = username;

        setChanged();
        notifyObservers(username);
    }


    public void implementData(){
        // Get the authentication data of our user from the reference.
        authData = userRef.getAuth();

        // This is the listener I have to get the data from. 
        userRef.child(authData.getUid()).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot snapshot) {

                UserSchema user = snapshot.getValue(UserSchema.class);
                // This guy needs to be used in the MainActivity appDrawer() method
                String userName = user.getName();
            }

            @Override
            public void onCancelled(FirebaseError firebaseError) {

            }
        });

    }
}

class MyObserver implements Observer {

    public void update(Observable observable, Object data) {
        // For now I just print it out to System.out
        System.out.println("Username:" + data);
    }
}

Then I notify my observers of the username change with the changeUsername() method:

public void changeUsername(String username) {
        this.username = username;

        setChanged();
        notifyObservers(username);
    }

In the MyObservable class, I have a MyObserver class that implements Observer with the update() method called whenever an observer has been updated. In the update() method for now, I just print out the username of the user to ensure something is actually happening.

This is where I need the data from the observer (In the MainActivity):

public class MainActivity extends AppCompatActivity {
    ...

    public void appDrawer(){

        IProfile profile = new ProfileDrawerItem()

                // I need the user's data here
                .withName("Test")
                .withEmail("[email protected]")
                .withIcon(R.drawable.avatar2);
    }

    ...

}

I have spent hours trying to 'react' to the events happening in the listener by trying to retrieve data to be used in my MainActivity but I'm not sure I'm using the Observable/Observer pattern properly, also since this is an Asynchronous event by Firebase to get data, using an Observer has been the best way to do this.

The appDrawer() method is called in my Activity's onCreate() .

How do I retrieve data from the Listener with an Observer, so I can use it elsewhere?

like image 510
Feyisayo Sonubi Avatar asked Jan 29 '16 23:01

Feyisayo Sonubi


1 Answers

I can't tell by your design what's really going on. Naming a class Listener then making it Observable seems counter-intuitive. A listener listens or observes. Nonetheless, it sounds like you have another class in the Listener that's an Observer so I'm a little lost but you seem unsure if you've implemented the pattern correctly. That I can clear up with an example.

public class MyObserver implements Observer {
    @Override
    public void update(Observable o, Object arg) {
        System.out.println(arg + " " + ((MyObservable)o).name);
    }
}

public class MyObservable extends Observable {

    public String name = "Observable";

    public void changeMe(String word) {
        setChanged();
        notifyObservers(word);
    }
}

public class Test {
    public static void main(String[] args) {
        MyObservable myObservable = new MyObservable();
        myObservable.addObserver(new MyObserver());
        myObservable.changeMe("Hello");
    }
}

The update method gives you the object you're observing as well as the arguments (the data you want shared with the observer) you passed into notifyObservers(). If you've done it like this then you should get the behavior you expect.

As you can see data can be sent to the observers that is outside or inside the observable. When you run it the output is...

Hello Observable

like image 74
ChiefTwoPencils Avatar answered Oct 16 '22 20:10

ChiefTwoPencils