Press enter to see results or esc to cancel.

Reagindo a eventos com Xamarin Forms e Firebase

Você provavelmente já precisou desenvolver uma aplicação que trocasse dados com outra aplicação em tempo real ou de forma muito rápida.

Imagine um cenário onde você tem um aplicativo para clientes e um aplicativo para vendedores.

Quando um cliente realizar um pedido, o novo pedido deve ser disparado para todos os vendedores em tempo real. Quando um vendedor selecionar o pedido para atende-lo, o pedido em questão deve ser removido da lista de novos pedidos.

Existem muitas formas para resolver este problema. Neste post vou utilizar para o exemplo um aplicativo Xamarin Forms e para resolver o problema dos pedidos irei integrar meu aplicativo ao Realtime Database do Firebase.

Programação Reativa

O conceito de programação reativa, entre outros pontos, diz que aplicações reativas devem:

  • Reagir a eventos – a natureza de ser orientada a eventos permite as demais qualidades;
  • Reagir a cargas – foco na escalabilidade ao invés de performance voltada a um usuário apenas;
  • Reagir a falhas – ser resiliente com a capacidade de recuperação em todos os níveis;
  • Reagir aos usuários – combinar as características acima para proporcionar uma experiência de usuário interativa.

Você pode ler um pouco mais e se inteirar do assunto no site do manifesto da programação reativa em https://www.reactivemanifesto.org/

Xamarin Forms

De acordo com o site da própria tecnologia:
“O Xamarin.Forms é um conjunto de ferramentas UI multi-plataforma que permite aos desenvolvedores criar facilmente layouts de interface de usuário nativos que podem ser compartilhados em Android, iOS e Windows Phone.” Ele utiliza o XAML da Microsoft (já conhecido por quem já trabalhou com WPF e Windows Store Apps) para elaboração do layout que será compartilhado entre as plataformas móveis (iOS, Android e Windows).

Firebase Realtime Databse

O Firebase é um portal desenvolvido e administrado pela Google. Ele possui diversos serviços desenvolvidos para integrar a sua aplicação. Dados estas caracteristicas, ele encaixa-se no conceito de um BaaS (backend as a Service). Um dos serviços provisionado pelo Firebase é o Realtime Database. Um banco de dados NoSQL hospedado na nuvem. Com ele, você armazena e sincroniza dados entre os seus usuários em tempo real. Ele utilizar o formato JSON para armazenar os dados e você pode interagir com ele diretamente do portal do Firebase.

Criando a base de dados no Firebase

Acesse o site do Firebase pelo seu browser através do endereço https://firebase.google.com

Faça login com sua conta do Google, e clique na opção Go To Console:

Menu Firebase

Clique na opção Adicionar Projeto, nomeie e selecione o país que irá hospedar a sua base de dados:

 

Dados do projeto firebase

Adicionar Projeto Firebase

Acesse o menu Database:

Menu Firebase

Clique no botão Primeiros Passos.

Após isto você será direcionado para sua Realtime Databse.

Para efeitos de demonstração deste post, vamos desativar a opção de autenticação da base de dados. Mas atenção! Isto significa que qualquer pessoa que detenha o endereço da sua realtime database poderá inserir, atualizar e excluir itens, portanto, NUNCA UTILIZE ASSIM EM PRODUÇÃO.

Altere as propriedades read and write para true no JSON e clique em publicar.

Regras Firebase

Para não me estender muito neste artigo vou abordar apenas o aplicativo do vendedor, então vamos precisar adicionar alguns pedidos manualmente (o que poderia ser feito por um aplicativo cliente sem problemas):

Clique no botão + ao lado do nome da base de dados para adicionar uma nova coleção:

Nome da collection

Preencha o nome da coleção com pedidos:

Nome da collection

Clique no + no final linha para adicionar as propriedades

Informe a chave (como se fosse um primary key) do pedido e depois clique novamente no + que aparecerá ao final da linha adicionada:

Inserindo dados

Para cada linha que você digitar o campo a esquerda deverá ser preenchida com nome da propriedade e a direita com o valor, assim como nos arquivos JSON. Para adicionar mais propriedades, clique no + ao lado da chave do pedido, neste exemplo no + ao lado do número 1. Preencha com as propriedades que serão utilizadas posteriormente no app e clique no botão Adicionar:

Inserindo dados

Dados salvos

O campo IdVendedor será utilizado no app para informar qual o vendedor irá atender este pedido. Para adicionar mais itens, repita o procedimento.

Criando o aplicativo Xamarin Forms

Para este exemplo, vou usar o Visual Studio Community 2017, update 15.4. O framework do Xamarin está na versão 4.7.10.33

Vamos utilizar o projeto Cross Plataform App para criar nosso projeto Xamarin Forms:

File > New Project > Cross-Plataform > Cross Plataform App (Xamarin)

New project Xamarin Forms

New project Xamarin Forms

Vamos utilizar MVVM nesta demo para realizar a comunicação do front com back, caso você não conheça e queira aprender mais sobre o assunto recomendo este vídeo https://www.youtube.com/watch?v=ZXcDM0EwalA&t=1099s da galera do Monkey Nights!

Vamos adicionar a classe base da nossa ViewModel:


public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Vamos precisar também de uma classe modelo que será a representação do nosso pedido, ela deve conter todas as propriedades do pedido que foi criado na nossa coleção de pedidos, acrescida de uma propriedade que irá armazenar a chave do pedido:


public class Pedido
{

    public string KeyPedido { get; set; }

    public string Cliente { get; set; }

    public decimal Preco { get; set; }

    public string Produto { get; set; }

    public int IdVendedor { get; set; }
}

A propriedade KeyPedido será preenchida com a Key do Pedido gerada pelo Firebase, você ver mais detalhes adiante.

Vamos criar também a ViewModel da nossa MainPage já com a lista de Pedidos e um Pedido que irá armazenar o pedido selecionado pelo usuário e também com um Command que será responsável por informar o Firebase que o vendedor irá atender o pedido:


public class MainPageViewModel : BaseViewModel
{

    private ObservableCollection<Pedido> _pedidos;

    public ObservableCollection<Pedido> Pedidos
    {

      get { return _pedidos; }

      set { _pedidos = value; OnPropertyChanged();}

    }

    public Pedido PedidoSelecionado;
    public ICommand AceitarPedidoCmd { get; set; }
}

É importante que a lista de pedidos seja do tipo ObservableCollection para que a tela seja notificada quando um novo item for incluído na lista, ou quando algum item for excluído.

Na nossa MainPage iremos ter uma ListView para receber os pedidos com um evento de ItemSelected e um Button para informar ao Firebase que o vendedor irá atender o pedido:

<ListView ItemsSource="{Binding Pedidos}" ItemSelected="ListView_OnItemSelected">
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell>
        <Grid>
           <Grid.ColumnDefinitions>
             <ColumnDefinition Width="*"></ColumnDefinition>
             <ColumnDefinition Width="*"></ColumnDefinition>
           </Grid.ColumnDefinitions>

           <Grid.RowDefinitions>
             <RowDefinition Height="Auto"></RowDefinition>
             <RowDefinition Height="Auto"></RowDefinition>
           </Grid.RowDefinitions>

           <Label Text="{Binding Produto}" Grid.Row="0" Grid.Column="0" FontSize="15"/>
           <Label Text="{Binding Preco}" Grid.Row="0" Grid.Column="1" FontAttributes="Bold" FontSize="15"/>
           <Label Text="{Binding Cliente}" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" FontSize="12"/>

       </Grid>
     </ViewCell>
   </DataTemplate>
 </ListView.ItemTemplate>
</ListView>

<Button Command="{Binding AceitarPedidoCmd}" Text="Atender"></Button>

Não esqueça de setar o BindingContext no code-behind da sua página:

BindingContext = new MainPageViewModel();

Neste momento vamos criar o nosso método Listerner de Pedidos e o método Aceitar Pedido. A partir de agora vamos começar a integrar nosso aplicativo com o Firebase.

Para isto vamos utilizar a biblioteca FirebaseDatabase.net da Step-up-labs: https://github.com/step-up-labs/firebase-database-dotnet

Vamos utilizar esta biblioteca pois ela é cross plataform, então não vamos precisar nos preocupar com as diferenças entre iOS e Android e suporta o .Net Standart 1.1.

A biblioteca deve ser instalada em todos os projetos da Solution. Você pode instalar pelo Package Manager Console executando o comando:

1
Install-Package FirebaseDatabase.net

Na MainPageViewModel.cs vamos adicionar o cliente do Firebase e o endereço da base de dados do firebase:

Acesse sua conta do Firebase novamente, entre na sua base de dados criada anteriormente e copie o endereço:

Vamos criar uma constante na nossa MainPageViewModel.cs para armazenar este valor:

private readonly string ENDERECO_FIREBASE = "https://demoapp-33406.firebaseio.com/";

Vamos criar também a propriedade do client do firebase e instancia-lo no método construtor da nossa viewmodel juntamente com a nossa lista de pedidos e o nosso command de Aceitar Pedidos:


private readonly FirebaseClient _firebaseClient;

public MainPageViewModel()
{
  _firebaseClient = new FirebaseClient(ENDERECO_FIREBASE);
  Pedidos = new ObservableCollection<Pedido>();
  AceitarPedidoCmd = new Command(() => AceitarPedido());
}

Criando o Listener de Pedidos:

Na MainPageViewModel.cs vamos criar o método Listener de Pedidos do Firebase. Ele irá realizar uma subscrição para a API Rest base de dados que entre outros, suporta a API de transmissão que você pode usar para notificações em tempo real.

Vamos utilizar o subscribe do tipo Pedido que foi definido anteriormente para o filho pedidos, que foi a base de dados que criamos anteriormente:

private void ListenerPedidos()
{
  _firebaseClient
    .Child("pedidos")
    .AsObservable<Pedido>()
    .Subscribe(d =>
    {
      if (d.EventType == FirebaseEventType.InsertOrUpdate)
      {
        if (d.Object.IdVendedor == 0)
          AdicionarPedido(d.Key, d.Object);
        else
          RemoverPedido(d.Key);
      }
      else if (d.EventType == FirebaseEventType.Delete)
      {
        RemoverPedido(d.Key);
      }
   });
}

Perceba que ao definirmos a função para o método subscribe podemos realizar a verificação se o tipo de Evento recebido é um InsertOrUpdate ou se é do tipo Delete.

Também iremos verificar se o IdVendedor é igual a 0 para adicionar à lista de pedidos ou para remover.

Você pode utilizar a regra de negócio que melhor se adequa a sua necessidade. Neste exemplo, novos pedidos devem ter o IdVendedor igual a 0 e quando algum vendedor selecionar o pedido para atendimento vamos informar o ID do vendedor neste campo para que ele não apareça mais na lista de novos pedidos.

Vamos adicionar também os métodos responsáveis por adicionar e remover um pedido da lista de pedidos:

private void AdicionarPedido(string key, Pedido pedido)
{
  Pedidos.Add(new Pedido()
  {
    KeyPedido = key,
    Cliente = pedido.Cliente,
    Produto = pedido.Produto,
    Preco = pedido.Preco
  });
}

private void RemoverPedido(string pedidoKey)
{
  var pedido = Pedidos.FirstOrDefault(x => x.KeyPedido == pedidoKey);
  Pedidos.Remove(pedido);
}

O listener já está preparado para receber as atualizações em tempo real da base de dados do Firebase. Para que ele seja ativado quando nosso aplicativo for executado, iremos chamar o método ListenerPedidos no método criador da MainPageViewModel.cs, que ficará da seguinte maneira:

public MainPageViewModel()
{
  _firebaseClient = new FirebaseClient(ENDERECO_FIREBASE);
  Pedidos = new ObservableCollection<Pedido>();
  AceitarPedidoCmd = new Command(() => AceitarPedido());

  ListenerPedidos();
}

Por fim, vamos adicionar o método AceitarPedido, que será chamado pelo nosso command AceitarPedidoCmd:

private void AceitarPedido()
{
  PedidoSelecionado.IdVendedor = 1;

  _firebaseClient
    .Child(&quot;pedidos&quot;)
    .Child(PedidoSelecionado.KeyPedido)
    .PutAsync(PedidoSelecionado);
}

Nete método estamos informando para o Firebase que estamos enviando um registro do tipo pedido, com uma determinada chave única para nossa coleção de pedidos. Ao recebe-lo o Firebase irá identificar que o pedido já existe e, porque estamos fazendo um Put, irá atualizar o pedido através da chave informada.

Estamos também informando o valor 1 na propriedade IdVendedor para que quando o Firebase enviar o evento para nosso listener o pedido seja removido da lista de novos pedidos.

No code behind da nossa página vamos adicionar o evento seleção de um item da lista:


private void ListView_OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
  _viewModel.PedidoSelecionado = e.SelectedItem as Pedido;
}

Este evento já está relacionado na propriedade ItemSelected da ListView da MainPage.

Selecione a sua plataforma de preferência como projeto de inicialização e execute o aplicativo.

Para realizar o teste e checar se o aplicativo está reagindo em tempo real as alterações realizadas no Firebase, você pode selecionar um item da lista de clicar no botão Atender, o item deverá sumir da lista, pois foi o ID do vendedor foi atualizado para o valor 1 no Firebase.

Você também pode incluir novos itens na coleção do Firebase e verificar se aparece em tempo real na lista de novos pedidos do aplicativo.

Legal, não é? O Firebase é uma ferramenta muito poderosa e que pode nos ajudar a resolver diversos problemas. Apesar da sequência de passos parecer grande, para a finalidade do problema que estamos resolvendo, acredito que foi uma sequência aceitável.

Você gostou? Funcionou? Caso tenha alguma dúvida entre em contato, terei prazer em ajudar!

Você pode baixar o código fonte completo deste exemplo no GitHub:

https://github.com/AmorimRob/XamarinForms-RealtimeDatabase

 

 

 

 

#Ubuntu

 

Referencias:

https://www.infoq.com/br/news/2013/11/programacao-reativa

https://www.reactivemanifesto.org/

https://developer.xamarin.com/guides/xamarin-forms/

https://firebase.google.com/products/database/?hl=pt-br

 

Foto usada no post: rawpixel.com

 

(Cross-post de http://rsamorim.azurewebsites.net/2017/11/07/reagindo-a-evento-com-xamarin-forms-e-firebase/ )

Tweet about this on TwitterShare on FacebookShare on LinkedInEmail this to someone
Comments

Leave a Comment