Mobile

16 mai, 2019

HotReload: desenvolvendo telas rapidamente para Xamarin.Forms grátis

Publicidade

O desenvolvimento de telas para Xamarin.Forms já foi abordado antes, e o assunto continua popular, mesmo depois de um ano.

É bem claro que a comunidade de Xamarin entendeu que precisa de uma forma mais rápida de desenvolver telas para Xamarin.Forms.

Até então, a comunidade estava dividida entre pessoas que tinham uma licença LiveXAML e estavam felizes, e pessoas que ainda sofriam para desenvolver telas.

Esse não é mais o caso, dado que agora existe uma solução simples, totalmente gratuita e open source: o HotReload.

Antes de tudo, já vou começar respondendo a pergunta principal:

  • Funciona mesmo?

Sim! Eu e o Robson Amorim utilizamos somente ele nos últimos dois meses em um chatbot que desenvolvemos aqui na Lambda3, e ele funcionou perfeitamente durante todo o projeto.

O HotReload é open source e foi feito principalmente por duas pessoas: Andrei e Stanislav. O fato do projeto ter o código aberto e aceitar contribuições tem contribuído para sua evolução rápida. De dois meses pra cá vimos várias melhorias no projeto, que continua sendo evoluído.

Hoje eu enxergo pelo menos três vantagens em utilizá-lo:

  • Totalmente gratuito
  • Funciona com qualquer IDE/Editor de texto
  • Permite visualizar a tela simultaneamente em quantos devices/emuladores você quiser

Xamarin.HotReload

Começar a utilizá-lo é extremamente simples – você precisa primeiro adicionar o pacote NuGet ao projeto compartilhado do Xamarin.Forms:

Install-Package Xamarin.HotReload

Em seguida, é necessário adicionar esse trecho de código no App.xaml.cs:

using Xamarin.Forms;
 
namespace HotReloadSample
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
#if DEBUG
            HotReloader.Current.Start(this);     
#endif
            MainPage = new NavigationPage(new MainPage());
        }
    }
}

Ao rodar o app ele já estará preparado para receber modificações no XAML para atualizar a tela. Agora é preciso fazer a IDE enviar essas modificações no XAML.

O jeito mais fácil se você estiver utilizando Visual Studio/Visual Studio for Mac é utilizando uma extensão. Para o Mac, a extensão pode ser baixada neste link, e para o Windows, ela está no Marketplace.

Caso tenham problemas na configuração da extensão, sugiro que leiam o README do projeto disponível aqui.

Agora a tela deve atualizar automaticamente ao salvar o XAML:

Xamarin Hot Reload
  • Utilizei o projeto InSpace como exemplo

Android

Se você estiver tentando configurar o HotReload em um emulador Android e não está conseguindo, talvez seja preciso redirecionar a porta com o adb. Execute o seguinte comando sempre que subir o emulador Android:

adb forward tcp:8000 tcp:8000

O executável adb fica dentro das pastas do Android SDK, neste caminho: {PASTA_ANDROID_SDK}/platform-tools.

Se estiver utilizando um dispositivo físico Android, você precisa configurá-lo conforme descrito aqui.

Utilizando HotReload com outras IDEs e Editores

No Mac eu tenho usado bastante o Rider da JetBrains junto com o Visual Studio for Mac. Portanto, preciso configurar o HotReload sem as extensões para que eu possa utilizá-lo no Rider, no Code, no Vim, ou em qualquer outro editor de minha preferência.

Para isso, é preciso buildar o projeto Observer do HotReload em modo Release, copiar o .exe gerado para a raiz do projeto Xamarin.Forms e utilizá-lo para observar as mudanças no seu diretório.

No Mac:

mono Xamarin.Forms.HotReload.Observer.exe

No Windows:

.\Xamarin.Forms.HotReload.Observer.exe

Caso a porta utilizada seja a padrão, ele enviará o XAML editado para os devices/emuladores que estiverem ouvindo.

Atualizando iOS e Android ao mesmo tempo

No nosso projeto queríamos ser capazes de ver as mudanças no Android e no iOS ao mesmo tempo. O HotReload já suporta esse cenário – só é preciso fazer algumas alterações.

Se assim como nós, você estiver usando o simulador iOS e o emulador Android, ambos rodando na mesma máquina, não será mais possível utilizar a mesma porta padrão do HotReload. Remova a inicialização do HotReload do arquivo App.xaml.cs.

Para o Android, a chamada vai ficar na MainActivity:

protected override void OnCreate(Bundle savedInstanceState)
{
    TabLayoutResource = Resource.Layout.Tabbar;
    ToolbarResource = Resource.Layout.Toolbar;
 
    base.OnCreate(savedInstanceState);
 
    global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
 
    var xfApplication = new App();
#if DEBUG
    HotReloader.Current.Start(xfApplication, 4290);
#endif
    LoadApplication(xfApplication);
}

Para o iOS, é preciso adicioná-la ao AppDelegate:

public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init();
 
    var xfApplication = new App();
#if DEBUG
    HotReloader.Current.Start(xfApplication, 4291);
#endif
    LoadApplication(xfApplication);
 
    return base.FinishedLaunching(app, options);
}

Agora o HotReload está rodando no Android na porta 4290, e no iOS na porta 4291. É necessário rodar novamente o comando de forward do adb, agora se atentando para utilizar a porta 4290 que foi utilizada no Android.

  • Dica: você não precisa estar debugando nenhuma das aplicações se estiver utilizando o Observer. O HotReload fica de olho em qualquer alteração no XAML e envia para as portas configuradas.

O último passo agora é configurar o Observer do HotReload para enviar as modificações para múltiplas portas. Dessa forma, é possível rodá-lo independente da IDE usada e do suporte a múltiplos IPs pelas extensões.

Passe os parâmetros dos endereços utilizados:

mono Xamarin.Forms.HotReload.Observer.exe u=http://127.0.0.1:4290,http://127.0.0.1:4291

Pronto! Duas telas sendo atualizadas simultaneamente!

A cereja no bolo

Apesar de já ter a solução funcionando corretamente no iOS e no Android, achei que ter que digitar os comandos para subir o Observer com as portas corretas e fazer o forward da porta do Android era muito repetitivo e passível de erro, por isso decidi automatizar tudo num script Cake.

Copiei o Observer para dentro da pasta /tools que o Cake utiliza por padrão e utilizei o seguinte script no meu build.cake, que já inclui todos os passos descritos acima:

Task("HotReload")
    .Does(() => {
        StartProcess("adb", "forward tcp:4290 tcp:4290");
 
        var urls = "u=<a class="vglnk" href="http://127.0.0.1:4290,http://127.0.0.1:4291" rel="nofollow"><span>http</span><span>://</span><span>127</span><span>.</span><span>0</span><span>.</span><span>0</span><span>.</span><span>1</span><span>:</span><span>4290</span><span>,</span><span>http</span><span>://</span><span>127</span><span>.</span><span>0</span><span>.</span><span>0</span><span>.</span><span>1</span><span>:</span><span>4291</span></a>";
        var windowsProcess = "./tools/Xamarin.Forms.HotReload.Observer.exe";
        var processName = IsRunningOnWindows() ? windowsProcess : "mono";
         
        var processSettings = new ProcessSettings()
        {
            Arguments = IsRunningOnWindows() ? urls : $"{windowsProcess} {urls}"
        };
 
        using (var hotReloadProcess = StartAndReturnProcess(processName, processSettings))
        {
            hotReloadProcess.WaitForExit();
        }
    });

Para executar o script Cake agora é só executar no Mac:

./build.sh -Target=HotReload

No Windows:

./build.ps1 -Target HotReload

Com isso, sempre que editar uma tela no XAML, tudo vai funcionar como mágica, tanto no Mac quanto no Windows.

Certifique-se de que o adb está no PATH de sua máquina. Caso contrário, você receberá um erro ao rodar o script Cake.

Conclusão

Para o meu uso, a melhor solução é a última, com o Cake, pois tenho um script muito simples que compartilho com todas as pessoas do time e que já faz tudo que preciso para atualizar minhas telas no iOS e Android ao mesmo tempo. Ainda consigo utilizá-lo de qualquer editor – até de um Notepad!

Editar XAML sem uma ferramenta de atualização é um impacto gigante na produtividade, e agora você não tem mais que se preocupar em pagar uma licença em dólar pra ter isso! É uma experiência muito parecida com o que existe na Web.

Espero que comece a utilizar nos seus projetos e sinta o mesmo ganho de produtividade que eu tenho sentido nos projetos em que atuo.

O sample utilizado neste artigo está no meu GitHub, para consulta de mais detalhes.

***

Este artigo foi produzido em parceria com a Lambda3. Leia outros conteúdos no blog da empresa: blog.lambda3.com.br