Sincronizzazione dei risultati da attività asincrone

2

In Android, ho spesso bisogno di ottenere risultati da più di un servizio che utilizza un pattern di callback asincrono e voglio sapere se c'è un modo migliore per gestire questo pattern rispetto a quello che sto facendo.

In questo momento il modo in cui lo gestisco è qualcosa di simile a questo: chiamo entrambi i servizi e li passo i miei callback. Nella richiamata per il servizio A, controllo e vedo se ho un risultato memorizzato nella cache dal servizio B. Se lo faccio, allora faccio qualsiasi cosa abbia bisogno di fare con loro. In caso contrario, memorizzo nella cache il risultato del servizio A. Faccio lo stesso nel callback per il servizio B.

Quindi, ad esempio, ho un'attività che mostra la posizione corrente dell'utente su una mappa. La mappa viene caricata in modo asincrono e richiama onMapReady . La richiesta di servizi di localizzazione richiama onConnected . In onMapReady , controllo se ho dei servizi di localizzazione. Se lo faccio, imposto la posizione sulla mappa all'ultima posizione dell'utente. In caso contrario, imposto la posizione su una posizione predefinita e memorizzo nella cache la mappa. In onConnected , controllo e vedo se ho la mappa. Se lo faccio, imposto la posizione sulla mappa all'ultima posizione dell'utente. Se non lo faccio, memorizzo nell'ultima posizione.

Questo schema funziona abbastanza bene quando ci sono solo due servizi coinvolti, ma posso immaginare scenari in cui potrei avere tre o più, e sembra maldestro. C'è un altro modo che dovrei gestire questo?

    
posta TBridges42 09.12.2016 - 16:16
fonte

3 risposte

1

La tua promessa / attività asincrona / qualsiasi libreria dovrebbe avere una funzione per gestire questo in modo nativo per te. C # ha Task.WhenAll , e c'è jQuery.when e amici simili in JS. Se il tuo non ha questa funzione, trova una nuova.

    
risposta data 08.01.2017 - 21:38
fonte
0

Dichiarazione di non responsabilità: non sono uno sviluppatore Android.

Vorrei che i callback mandassero i loro risultati in una coda e si sedessero lettura dalla coda fino all'arrivo di un numero sufficiente di risultati (con un timeout opzionale).

Tuttavia, non è conveniente inviare i risultati di tipi diversi lungo la stessa coda. Se possibile, (leggermente) diverse classi di risultati possono implementare un'interfaccia comune. Per risultati estremamente disparati, potrei usare più code, leggendole in sequenza.

Se tutto quello che mi interessa è aspettare che arrivino tutti i risultati, e poi procedere, questo è sufficiente.

Se c'è una sequenza ragionevole quando posso iniziare l'elaborazione di un risultato in qualche modo, anche prima che arrivi l'altro risultato, posso ordinare le letture dalle code per riflettere che:

// Imagine we're trying to help user see if a bus is coming.
// APIs are imaginary throughout.
// We wrap callback-accepting services so that the callbacks
// simply put the result into the queue given.
connection_service.askForConnection(connection_queue);
location_service.askForLocation(location_queue);
// Start using the location, connection may be arriving.
location = location_queue.get();
BusStop the_stop = determineBusStop(location);  // from offline data.
connection = connection_queue.get();
StopInfo info = BusStop.getApproachingBuses(connection);

Per il tuo caso particolare, una mappa geografica e la posizione, il tuo approccio, quello con posizioni nascoste e tessere mappa, sembra più user-friendly: c'è sempre qualcosa da mostrare all'utente, anche se non è l'ultimo.

Peccato che i tuoi servizi sembrino non parlare nella lingua di FutureTask s.

    
risposta data 09.03.2017 - 23:18
fonte
-1

A volte uso un conteggio, impostato sul numero di elementi che sono a conoscenza che sto per essere in attesa. Quindi effettuare le varie chiamate con chiamate ritardate. In ogni richiamo, catturo ciò che mi serve dagli argomenti specifici di quella richiamata e quindi chiamo una routine comune.

La routine comune decrementa il conteggio e se il conteggio è diverso da zero ritorna senza fare altro. Quando il conteggio arriva a zero, esegue un codice che dipende dal completamento di tutti i callback.

(Questo potrebbe essere fatto usando oggetti o chiusure.)

A volte uso un conteggio semplice quando lo so ed è localmente ovvio; altre volte incremento dinamicamente il conteggio, ad esempio quando devo attendere che si verifichi una richiamata, e quindi quella richiamata potrebbe avere bisogno di emettere un'altra chiamata che coinvolge un'altra richiamata, a seconda delle risposte della richiamata precedente .

Sto lavorando con l'API di Chrome, che adora questi callback ritardati e implora una buona quantità di macchinari per coordinare i vari callback.

    
risposta data 09.12.2016 - 20:37
fonte

Leggi altre domande sui tag