O desenvolvimento de telas para Xamarin.Forms já foi abordado antes por aqui, e o assunto continua popular, mesmo depois de 1 ano passado. É 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, vou já começar respondendo a pergunta principal:
mas funciona mesmo?
Sim! Eu e o Robson Amorim utilizamos somente ele nos últimos 2 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 2 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
Agora é 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 aqui, para o Windows, ela está no Marketplace.
Caso tenha problemas na configuração a extensão, sugiro ler o README do projeto aqui.
Agora a tela deve atualizar automaticamente ao salvar o XAML:
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 no 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 que eu prefira.
Para isso é preciso buildar o projeto Observer do HotReload em modo Release, copiar o .exe
gerado para a raíz do projeto Xamarin.Forms e utilizá-lo para ficar observando 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 maneira é 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, eu 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?.
Eu 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=http://127.0.0.1:4290,http://127.0.0.1:4291"; 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 que o
adb
está no PATH da 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 para 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 tenho nos projetos em que atuo.
O sample utilizado nesse post está no meu GitHub para consulta de mais detalhes.
Imagem usada no post: David Švihovec, Unsplash
Mahmoud Ali
Desenvolvedor de Software na Lambda3, Microsoft MVP, amante de um bom café ☕️ e uma boa cerveja 🍺.