2016-07-11 12 views
1

Das Problem wird von der Initialisierung und dem Abrufen von Daten von Firebase übernommen, jedoch werde ich dies in Pseudo übersetzen, damit diejenigen, die nicht vertraut sind, auch beitragen können. Bitte beachten Sie den folgenden Code: `Was ist das korrekte Architekturdesign hier?

//Given the following API (from Firebase) 
MyRemoteDBClass.asyncAuthenticate(initCompletedListener); 
MyRemoteDBClass.asyncDataFetch(fetchCompletedListener) 
// of course you have to authenticate before fetching the data 
Class MyClassA.init() 
{ 
    MyRemoteDBClass myRemoteDBClassInstance = new MyRemoteDBClass(); 
    myRemoteDBClassInstance.asyncAuthenticate(some_listener); 
} 
// Then somewhere in the app: 
Class MyClassB.asyncDataFetch(MyRemoteDBClass myRemoteDBClassInstance){ 
    myRemoteDBClassInstance.asyncDataFetch(myClassBObject_as_listener) 
}` 

Das Problem ist, dass die Anrufe von KlasseA und ClassB in Timeline ziemlich nahe sind, und ich weiß nicht, ob ich das asyncFetch vor oder nach der init von myRemoteDBClassInstance rufen erhalten war schon fertig.
Wie kann ich versprechen, dass ich die Methode myRemoteDBClassInstance.asyncDataFetch in MyClassB aufrufen muss, nachdem die Initialisierung abgeschlossen wurde?

+0

Sie können die 'init()' Operation blockieren, so dass auf die Authentifizierung gewartet wird. Sie benötigen ein "CountDownLatch" (initialisiert mit einem Wert von 1), das zwischen dem Listener und der 'init()' Methode geteilt wird. Im Listener können Sie 'latch.countDown()' und in 'init()' - 'latch.await()' –

Antwort

2

Machen Sie Ihre some_listener nehmen Sie eine CompletableFuture, und lösen Sie es, sobald die asyncAuthenticate abgeschlossen ist. Es wäre so etwas wie dies am Ende aussehen:

CompletableFuture<Void> future = new CompletableFuture<>(); 
Listener some_listener = new Listener() { 
    @override onAuthComplete() { future.complete(null); } 
    //... 
}; 

// Guts of your MyClassA.init 
MyRemoteDBClass myRemoteDBClassInstance = new MyRemoteDBClass(); 
myRemoteDBClassInstance.asyncAuthenticate(some_listener); 

// ... 

// Guts of your MyClassB.asyncDataFetch 
future.get(); // Wait for auth to complete 
myRemoteDBClassInstance.asyncDataFetch(other_listener); 

Ich mag eine Zukunft verwenden, da es uns etwas nützlicher als ein Void später zurückkehren kann, oder Verkettung von Asynchron ausführen später schön nennt.

+0

verwenden. In diesem Fall sollten wir den von mir vorgeschlagenen Ansatz verwenden und in welchen Fällen der von Ihnen vorgeschlagene Ansatz? –

+1

@GauravaAgarwal Es hängt vom gewünschten Verhalten ab. Michaels Ansatz "wartet" darauf, dass der benötigte Zustand erreicht wird, verzögert den Abruf, macht es aber am Ende. Ihre Vorgehensweise würde nur dazu führen, dass das Fetch nicht erledigt wird. – Fildor

+0

Der Ansatz von CompletableFuture ist interessant. Ich werde es mir ansehen. Danke – user3734429

1

Ich würde einen Zustand in MyClassA initialisieren, um einen Datensatz zu behalten, ob er initialisiert wird. Dann überprüfen Sie diesen Status in MyClassB.

Class MyClassA.init() 
{ 
    MyRemoteDBClass myRemoteDBClassInstance = new MyRemoteDBClass(); 
    myRemoteDBClassInstance.asyncAuthenticate(some_listener); 
    static boolean initialized = true;//only sample code 
} 
static boolean MyClassA.isInitialized() {return initialized ;} 

// Then somewhere in the app: 
Class MyClassB.asyncDataFetch(MyRemoteDBClass myRemoteDBClassInstance){ 
    if (MyClassA.isInitialized()) { //only sample code 
    myRemoteDBClassInstance.asyncDataFetch(myClassBObject_as_listener) 
} 
} 
+0

Sie möchten vorsichtig sein, da Ihr Boolean von innerhalb eines anderen Threads gesetzt wird. Ich würde stattdessen 'AtomicBoolean' verwenden. Und mit einer 'static' -Variablen wird das Testen von Code viel weniger Spaß machen - und eine unnötige Bindung zwischen' MyClassA' und 'MyClassB' entsteht. –

+0

Was ist, wenn es nicht initialisiert ist? Schleife immer und immer wieder, bis es ist? – user3734429

+0

@MichaelAnderson Ich biete nur grundlegende Lösung der Überprüfung, ob die Klasse initialisiert wird. Es gibt keine klare Sichtbarkeit, wenn "initialisiert" eine Instanzvariable sein kann, da der Benutzer nur einen sehr begrenzten Basiscode veröffentlicht hat. –