Olá pessoal! Tudo bem? Hoje vamos começar um dos tópicos mais complexos do Xamarin.Forms na minha opinião, pois ele é a porta de entrada para os recursos específicos de cada sistema operacional: O DependencyService, serviço de injeção de dependência do Xamarin.Forms.
Veja, até o presente momento, quase todos os artigos aqui no blog não encostavam nos projetos específicos de cada sistema operacional, com exceção da forma como usamos imagens no Xamarin.Forms, já que a forma de usar imagens muda conforme o sistema operacional.
Claro, já fizemos algo semelhante com a classe Device, mas o uso do DependencyService é o que realmente permite acesso a todos os recursos exclusivos de cada sistema operacional. Neste primeiro artigo, vamos aprender como implementar a lógica básica de injeção de dependência do Xamarin.Forms. Nos próximos, vamos desbravar os recursos individuais – mesmo que o código fonte seja semelhante entre as plataformas.
Como sempre, fique à vontade para baixar o código fonte deste artigo para estudos.
Quando estamos pensando em usar recursos de cada sistema operacional, o primeiro passo é pensar o que queremos acessar de forma que cada sistema operacional tenha seu código e o Xamarin.Forms consegue enxergar sem precisar escolher o código certo.
Para isso, criamos uma interface com a lista dos métodos que serão implementados em cada plataforma no projeto do Xamarin.Forms. Neste exemplo, vamos apenas fazer com que cada plataforma devolva uma mensagem de texto específica – sim, isto é algo que a classe Device consegue fazer]l3, mas o foco deste artigo é entender a lógica do DependencyService.
public interface IExemplo { string MensagemCustomizada(); }
Agora vamos até o projeto do Android criar a classe que implementa a interface IExemplo
. Desta forma, teoricamente é esta implementação que será usada no Android.
namespace XF_DependencyService01.Droid { public class ExemploNoAndroid : IExemplo { public string MensagemCustomizada() { return "Esta mensagem só existe no Android"; } } }
Eu digo teoricamente porque ainda não usamos o DependencyService. Precisamos marcar esta classe para que ela seja injetada. Reparou que, ao contrário de todos os outros exemplos de código que eu coloco, o trecho acima inclui o namespace
? Isso acontece porque precisamos colocar este atributo acima do namespace
:
[assembly: Xamarin.Forms.Dependency(typeof(ExemploNoAndroid))]
Obrigatoriamente, precisamos colocar o atributo assembly:Xamarin.Forms.Dependency()
e passar como parâmetro o tipo da classe (via typeof
) que estamos implementando. Neste caso, a classe ExemploNoAndroid
implementa a interface IExemplo
. Então o tipo de classe que será injetada é ExemploNoAndroid
. Veja o código completo, agora sim pronto para a injeção de dependência:
using XF_DependencyService01.Droid; [assembly: Xamarin.Forms.Dependency(typeof(Exemplo))] namespace XF_DependencyService01.Droid { public class ExemploNoAndroid : IExemplo { public string MensagemCustomizada() { return "Esta mensagem só existe no Android"; } } }
De forma análoga, vamos criar a classe ExemploNoIos
no projeto do iOS, implementar a interface IExemplo
e marcá-la como injetável com o atributo assembly: Xamarin.Forms.Dependency
.
using XF_DependencyService01.iOS; [assembly: Xamarin.Forms.Dependency(typeof(ExemploNoIos))] namespace XF_DependencyService01.iOS { public class ExemploNoIos : IExemplo { public string MensagemCustomizada() { return "Esta mensagem só existe no iOS"; } } }
Com isso, temos classes em cada sistema operacional que implementam a interface IExemplo
. Note duas coisas:
- Não precisamos usar o mesmo nome de classe em cada plataforma, desde que as classes implementem a mesma interface.
- Podemos ter outros métodos nas classes de cada plataforma, mas o projeto do Xamarin.Forms evidentemente só tem acesso aos métodos cujas assinaturas estão na interface. Neste caso, apenas o método
MensagemCustomizada()
.
Agora vamos montar um app bem simples, com uma tela e um botão na tela. O botão será usado para mostrar via alerta a mensagem vinda de cada sistema operacional.
<ContentPage.Content> <StackLayout> <Button Text="Clique aqui" Clicked="Button_OnClicked" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" /> </StackLayout> </ContentPage.Content>
Quando o botão é clicado, o método Button_OnClicked
usará a classe de cada sistema operacional para executar e mostrar o resultado do método MensagemCustomizada()
. Mas como fazer isso? Através do método DependencyService.Get
. Através da injeção de dependência, esta chamada procura qual classe marcada como injetável implementou a interface IExemplo
.
Ao executarmos o projeto no Android, o único resultado é a classe ExemploNoAndroid
e ao executarmos o projeto no iOS, o único resultado é a classe ExemploNoIos
. É assim que acessamos o código individual em cada sistema.
Vale destacar que cada plataforma precisa ter a implementação das classes injetadas via DependencyService, senão o app é encerrado com um erro durante a execução.
private async void Button_OnClicked(object sender, EventArgs e) { var exemplo = DependencyService.Get<IExemplo>(); await DisplayAlert("Atenção", exemplo.MensagemCustomizada(), "Ok"); }
Veja o resultado:


Lembre-se que o que realmente executamos é o projeto de cada plataforma, que por sua vez usa o projeto do Xamarin.Forms. Assim, uma plataforma não enxerga a outra (claro) e apenas uma implementação estará disponivel no app. É usando este raciocínio que conseguiremos usar os recursos individuais do iOS e do Android dentro do Xamarin.Forms sem que o código de um sistema atrapalhe o outro. Até a próxima!
[]’s
Paulo Roberto