×
Namespaces

Variants
Actions
Revision as of 23:04, 29 October 2013 by kiran10182 (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Implementando o GeoCordinateWatcher como um serviço reativo

From Nokia Developer Wiki
Jump to: navigation, search

Este artigo explica como usar Rx para subscrever eventos de geolocalização.

SignpostIcon XAML 40.png
WP Metro Icon WP8.png
SignpostIcon WP7 70px.png
Article Metadata

Compatibilidade
Plataforma(s): Windows Phone 7.5 and later
Windows Phone 8
Windows Phone 7.5

Platform Security
Capabilities: Location

Artigo
Tradução:
Por paulo.morgado
Última alteração feita por kiran10182 em 29 Oct 2013

Contents

Introdução

Com Rx, eventos são cidadãos de primeira classe que podem ser componíveis e passados a outros objetos de forma muito simples.

Implementando O GeoCoordinateWatcher Como Um Serviço Reativo

As Extensões Reativas (Rx) são uma biblioteca para composição de programas assíncronos e baseados em eventos usando sequências observáveis e operadores estilo-LINQ. Usando Rx, os desenvolvedores representam correntes assíncronas de dados com Observáveis, consultam (query) correntes assíncronas de dados usando operadores LINQ e parametrizam a concorrência das correntes de dados assíncronas usando agendadores (Schedulers). Pondo de forma simples, Rx = Observables + LINQ + Schedulers.” – da página da MSDN.

A biblioteca providencia também um considerável número de auxiliares que facilitam encapsular enventos em observáveis.

Encapsular o GeoCoordinateWatcher como um serviço reativo é muito simples. Tudo o que é necessário é expor os eventos como observáveis:

public class GeoCoordinateReactiveService : IGeoCoordinateReactiveService, IDisposable
{
private readonly GeoCoordinateWatcher geoCoordinateWatcher = new GeoCoordinateWatcher();
 
public GeoCoordinateReactiveService()
{
this.StatusObservable = Observable
.FromEventPattern<GeoPositionStatusChangedEventArgs>(
handler => geoCoordinateWatcher.StatusChanged += handler,
handler => geoCoordinateWatcher.StatusChanged -= handler);
 
this.PositionObservable = Observable
.FromEventPattern<GeoPositionChangedEventArgs<GeoCoordinate>>(
handler => geoCoordinateWatcher.PositionChanged += handler,
handler => geoCoordinateWatcher.PositionChanged -= handler);
}
 
public IObservable<EventPattern<GeoPositionStatus> StatusObservable { get; private set; }
 
public IObservable<EventPattern<GeoPosition<GeoCoordinate>> PositionObservable { get; private set; }
}

E assim, em vez dos eventos StatusChanged e PositionChanged temos respectivamente as correntes de instâncias de EventPattern<TEventArgs> StatusObservable e PositionObservable.

Mas a classe EventPattern<TEventArgs> inclui a fonte do evento e os seus argumentos em propriedades que são demasiado para as nossas necessidades. Usando normais operadores LINQ podemos converter as correntes de instâncias de EventPattern<TEventArgs> em correntes dos valores pretendidos.

public class GeoCoordinateReactiveService : IGeoCoordinateReactiveService, IDisposable
{
private readonly GeoCoordinateWatcher geoCoordinateWatcher = new GeoCoordinateWatcher();
 
public GeoCoordinateReactiveService()
{
this.StatusObservable = Observable
.FromEventPattern<GeoPositionStatusChangedEventArgs>(
handler => geoCoordinateWatcher.StatusChanged += handler,
handler => geoCoordinateWatcher.StatusChanged -= handler)
.Select(ep => ep.EventArgs.Status);
 
this.PositionObservable = Observable
.FromEventPattern<GeoPositionChangedEventArgs<GeoCoordinate>>(
handler => geoCoordinateWatcher.PositionChanged += handler,
handler => geoCoordinateWatcher.PositionChanged -= handler)
.Select(ep => ep.EventArgs.Position);
}
 
public IObservable<GeoPositionStatus> StatusObservable { get; private set; }
 
public IObservable<GeoPosition<GeoCoordinate>> PositionObservable { get; private set; }
}

Usando O GeoCoordinateReactiveService

Tendo criado o envelope Rx (wrapper) para o GeoCoordinateWatcher demonstrarei agora como pode ser usado numa aplicação simples.

A aplicação apresentará o estado do serviço, a posição e a distância percorrida.

Nesta aplicação simples o serviço será exposto através de uma propriedade singleton da classe App:

public partial class App : Application
{
// ...
 
public static IGeoCoordinateReactiveService GeoCoordinateService { get; private set; }
 
public App()
{
// ...
 
InitializePhoneApplication();
 
// ...
}
 
// ...
 
private void InitializePhoneApplication()
{
// ...
 
GeoCoordinateService = new GeoCoordinateReactiveService();
 
// ...
 
}
 
// ...
 
}

Obter o estado do serviço é muito simples. Apenas requere subscrever o StatusObservable. Uma vez que pretendemos apresentar o estado, precisamos de observá-lo no dispatcher:

App.GeoCoordinateService.StatusObservable
.ObserveOnDispatcher()
.Subscribe(this.OnStatusChanged);

Para a posição fazemos o mesmo com o PositionObservable:

App.GeoCoordinateService.PositionObservable
.ObserveOnDispatcher()
.Subscribe(this.OnPositionChanged);

Obter a dist�ncia percorrida parece ser mais complicado porque temos de manter registo da posi��o anterior e calcular a dist�ncia percorrida cada vez que a posi��o muda. Mas � aqui que a Rx mostra as suas vantagens com os seus operadores. Se combinarmos a o observ�vel da posi��o com o observ�vel da posi��o saltando uma posi��o usando operador zip obtemos um observ�vel com a posi��o anterior e a atual. E se aplicarmos um seletor, obtemos apenas a dist�ncia percorrida:

App.GeoCoordinateService.PositionObservable
.Zip(
App.GeoCoordinateService.PositionObservable.Skip(1),
(p1, p2) => p1.Location.GetDistanceTo(p2.Location))
.ObserveOnDispatcher()
.Subscribe(this.OnDistanceChanged);

A implementação complete pode ser encontrada aqui.

Recursos

This page was last modified on 29 October 2013, at 23:04.
139 page views in the last 30 days.