Namespaces

Variants
Actions

Please note that as of October 24, 2014, the Nokia Developer Wiki will no longer be accepting user contributions, including new entries, edits and comments, as we begin transitioning to our new home, in the Windows Phone Development Wiki. We plan to move over the majority of the existing entries over the next few weeks. Thanks for all your past and future contributions.

Implementando o GeoCordinateWatcher como um serviço reativo

From 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 20:04.
213 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×