2016-01-29 32 views
5

Sto utilizzando la libreria MaterialDrawer per creare un cassetto semplice per la mia app, alcune delle istanze di classi nella libreria richiedono una stringa passata al loro interno quando vengono chiamate. Un esempio è la classe IProfile:Come implementare un Observer per ottenere dati da un listener?

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

cui il metodo withName() prende in una stringa.

Ho creato una classe MyObservable.java (extends Observable) che intendo utilizzare per ottenere i dati da utilizzare nel mio MainActivity che ha implementato la libreria MaterialDrawer. In questa classe, ho un metodo implementData() che ha il mio listener per ciò di cui ho bisogno dal mio database Firebase.

Questo è ciò che sembra:

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); 
    } 
} 

Poi notificare i miei osservatori del cambiamento nome utente con il metodo changeUsername():

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

     setChanged(); 
     notifyObservers(username); 
    } 

Nella classe MyObservable, ho una classe MyObserver che implementa Observer con il metodo update() chiamato ogni volta che un osservatore è stato aggiornato. Per il metodo update() per ora, stampo semplicemente lo username dell'utente per assicurarmi che qualcosa stia effettivamente accadendo.

Questo è dove ho bisogno i dati dall'osservatore (Nella 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); 
    } 

    ... 

} 

ho passato ore a cercare di 'reagire' agli eventi che accadono in chi ascolta, cercando di recuperare i dati da utilizzare nella mia MainActivity ma non sono sicuro di utilizzare correttamente il pattern Observable/Observer, anche perché si tratta di un evento Asincrono di Firebase per ottenere i dati, utilizzando un Observer è stato il modo migliore per farlo.

Il metodo appDrawer() è chiamato in Attività onCreate().

Come faccio a recuperare i dati dal listener con un osservatore, quindi posso usarlo altrove?

risposta

13

Non riesco a capire dal tuo progetto cosa stia realmente succedendo. Assegnare un nome a una classe Listener e quindi renderlo Observable sembra controintuitivo. Un ascoltatore ascolta o osserva. Tuttavia, sembra che tu abbia un'altra classe nello Listener che sia un Observer quindi sono un po 'perso ma non sei sicuro di aver implementato correttamente il modello. Che posso chiarire con un esempio.

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"); 
    } 
} 

Il metodo update ti dà l'oggetto che si sta osservando così come gli argomenti (i dati desiderati condiviso con l'osservatore) è stato superato in notifyObservers(). Se l'hai fatto in questo modo, dovresti ottenere il comportamento che ti aspetti.

Come si può vedere i dati possono essere inviati agli osservatori che si trovano all'esterno o all'interno dell'osservabile. Quando lo esegui, l'output è ...

Ciao osservabili

+0

'notifyObservers (String)' devono essere chiamati da 'changeme()'. – cybergen

+1

@cybergen, "dovrebbe essere" è probabilmente un po 'restrittivo per me. È pubblico quindi è appositamente esposto. Direi che nel caso generale chiamare 'notifyObservers' in ogni metodo che cambia lo stato può essere eccessivo. Vedo il tuo punto però. Nel caso dell'OP non importa in quanto c'è solo una notifica. Lo modificherò per il tuo piacere di visione e quindi corrisponde meglio al codice di OP. – ChiefTwoPencils

+0

Oh wow, grazie mille, quindi posso avere il metodo 'changeMe' restituire la stringa che viene aggiornata invece e gli osservatori non devono essere aggiunti all'interno dell'osservabile sì? –