Blog: mobile

Arquitetura iOS VIPER

VIPER

AINDA EM REVISÃO DE CONTEÚDO E ESTUDO.

Experiência de construção de LEGO transferida para o design do aplicativo iOS VIPER é o nosso último candidato, o que é particularmente interessante porque não vem da categoria MV (X).

Agora, você deve concordar que a granularidade nas responsabilidades é muito boa. VIPER faz outra iteração sobre a ideia de separar responsabilidades e, desta vez, temos cinco camadas.

Interator - contém lógica de negócios relacionada aos dados ( Entidades ) ou rede, como criar novas instâncias de entidades ou buscá-las no servidor. Para esses propósitos, você usará alguns serviços e gerenciadores que não são considerados parte do módulo VIPER, mas sim uma dependência externa. Apresentador - contém a lógica de negócios relacionada à IU (mas independente do UIKit ), invoca métodos no Interator . Entidades - seus objetos de dados simples, não a camada de acesso a dados, porque isso é responsabilidade do Interator . Roteador - responsável pelos trechos entre os módulos VIPER . Basicamente, o módulo VIPER pode ser uma tela ou toda a história do usuário de seu aplicativo - pense na autenticação, que pode ser uma tela ou várias outras relacionadas. Quão pequenos são os seus blocos de “LEGO”? - Você decide.

Image

Se compararmos com o tipo MV (X), veremos algumas diferenças na distribuição de responsabilidades: A lógica do modelo (interação de dados) mudou para o Interator com as Entidades como estruturas de dados burras. Apenas as funções de representação da IU do Controller / Presenter / ViewModel foram movidas para o Presenter, mas não os recursos de alteração de dados. VIPER é o primeiro padrão que aborda explicitamente a responsabilidade da navegação, que deve ser resolvida pelo Roteador. A maneira adequada de fazer o roteamento é um desafio para os aplicativos iOS, os padrões MV (X) simplesmente não resolvem esse problema. O exemplo não cobre o roteamento ou interação entre os módulos , já que esses tópicos não são cobertos pelos padrões MV (X).

Mais uma vez, de volta aos recursos : Distribuição - sem dúvida, VIPER é um campeão em distribuição de responsabilidades. Testabilidade - sem surpresas aqui, melhor distribuição - melhor testabilidade. Fácil de usar - finalmente, os dois acima têm custo de manutenção, como você já imaginou. Você tem que escrever uma grande quantidade de interface para classes com responsabilidades muito pequenas.

E quanto ao LEGO?

Ao usar o VIPER, você pode sentir vontade de construir o Empire State Building com blocos de Lego, e isso é um sinal de que você tem um problema . Talvez seja muito cedo para adotar o VIPER para sua aplicação e você deva considerar algo mais simples. Algumas pessoas ignoram isso e continuam atirando canhões nos pardais. Presumo que eles acreditem que seus aplicativos irão se beneficiar do VIPER pelo menos no futuro, mesmo que agora o custo de manutenção seja excessivamente alto. Se você acredita da mesma forma, recomendo que experimente o Generamba - uma ferramenta para gerar esqueletos VIPER. Embora para mim, pessoalmente, pareça usar um sistema de mira automatizado para canhão, em vez de simplesmente dar um estilingue

Arquitetura iOS MVC, MVP, MVVM

AINDA EM REVISÃO DE CONTEÚDO E ESTUDO.

Dando continuidade ao aprendizado sobre Padrões e Arquiteturas, me mantenho nos padrões mais usados para Mobile seja iOS ou Android ao meu ver.

Fundamentos de MV (X) Existem muitas opções quando se trata de padrões de design de arquitetura: MVC ,MVP, MVVM

Os 3 MV's pressupõem colocar as entidades do aplicativo em uma das 3 categorias:

Modelos - responsáveis ​​pelos dados de domínio ou uma camada de acesso a dados que manipula os dados.

Visualizações - responsável pela camada de apresentação, para o ambiente iOS pense em tudo começando com o prefixo ' UI '. Como o mediador entre o Model e a View, gteral responsável por alterar o Model , reagindo às ações do usuário realizadas na View e atualizando a View com as mudanças do Model.

MVC Tradicional por assim dizer, é um pouco diferente do MVC da Apple.

Image

Cacau MVC O Controlador é um mediador entre a Visualização e o Modelo para que eles não se conheçam. O menos reutilizável é o Controlador e isso geralmente é bom para nós, já que devemos ter um lugar para toda aquela lógica de negócios complicada que não se encaixa no Modelo .

Em teoria, parece muito simples, mas você sente que algo está errado, certo? Você até ouviu pessoas não abreviando MVC como o controlador do Massive View . Além disso, o descarregamento do controlador de visualização tornou-se um tópico importante para os desenvolvedores iOS. Por que isso acontece se a Apple apenas pegou o MVC tradicional e o melhorou um pouco?

MVC da Apple

Realistic Cocoa MVC Cocoa MVC incentiva você a escrever controladores de visualização massiva , porque eles estão tão envolvidos no ciclo de vida de visualização que é difícil dizer que são separados. Embora você ainda tenha a capacidade de descarregar parte da lógica de negócios e da transformação de dados para o Modelo , você não tem muita escolha quando se trata de descarregar trabalho para a Visualização, na maioria das vezes, toda a responsabilidade da Visualização é enviar ações para o controlador . O controlador de visualização acaba sendo um delegado e uma fonte de dados de tudo, e geralmente é responsável por despachar e cancelar as solicitações de rede e ... você escolhe.

Image

A célula, que é a View configurada diretamente com o Model , então as diretrizes do MVC são violadas, mas isso acontece o tempo todo, e geralmente as pessoas não acham que está errado. Se você seguir estritamente o MVC, deverá configurar a célula a partir do controlador e não passar o modelo para a visualização , o que aumentará ainda mais o tamanho do seu controlador .

Cocoa MVC não é abreviado como o Controlador Massive View. O problema pode não ser evidente até que chegue ao Teste de Unidade (esperançosamente, em seu projeto). Uma vez que seu controlador de visualização está fortemente acoplado com a visualização, torna-se difícil testar porque você tem que ser muito criativo ao simular visualizações e seu ciclo de vida, ao escrever o código do controlador de visualização de tal forma que sua lógica de negócios seja separada tanto quanto possível a partir do código de layout de visualização.

--+++
A montagem MVC pode ser realizada no controlador de visualização de apresentação
Isso não parece muito testável, certo? Podemos mover a geração de saudação para a nova classe GreetingModel e testá-la separadamente, mas não podemos testar nenhuma lógica de apresentação (embora não haja muito dessa lógica no exemplo acima) dentro do GreetingViewController sem chamar os métodos relacionados ao UIView diretamente ( viewDidLoad, didTapButton) que pode causar o carregamento de todas as visualizações, e isso é ruim para o teste de unidade.
Na verdade, carregar e testar UIViews em um simulador (por exemplo, iPhone 4S) não garante que funcionaria bem em outros dispositivos (por exemplo, iPad), então eu recomendo remover “Host Application” de sua configuração de destino de teste de unidade e execute seus testes sem seu aplicativo em execução no simulador.
As interações entre a visualização e o controlador não são realmente testáveis ​​com testes de unidade
--++++

Com tudo isso dito, pode parecer que Cocoa MVC é um padrão muito ruim para escolher. Mas vamos avaliá-lo em termos de características definidas no início do artigo: Distribution - a View e o Model de fato separados, mas a View e o Controller estão fortemente acoplados.

Testabilidade - devido à má distribuição, você provavelmente só testará seu modelo. Facilidade de uso - a menor quantidade de código entre outros padrões. Além disso, todos estão familiarizados com ele, portanto, é facilmente mantido, mesmo por desenvolvedores inexperientes.

Cocoa MVC é o padrão de sua escolha se você não está pronto para investir mais tempo em sua arquitetura e sente que algo com custo de manutenção mais alto é um exagero para seu projeto de estimação minúsculo.

Cocoa MVC é o melhor padrão arquitetônico em termos de velocidade de desenvolvimento.

MVP

Variante de visão passiva do MVP Não se parece exatamente com o MVC da Apple? Sim, é verdade, e seu nome é MVP (variante do modo de exibição passivo). Mas espere um minuto ... Isso significa que o MVC da Apple é de fato um MVP? Não, não é, porque se você se lembrar, lá, o View está fortemente acoplado ao Controller , enquanto o mediador do MVP, Presenter, não tem nada a ver com o ciclo de vida do view controller, e o View pode ser zombado facilmente, então não há código de layout no Presenter , mas ele é responsável por atualizar a View com dados e estado.

Image

E se eu dissesse a você, o UIViewController é o View. Em termos de MVP , as subclasses de UIViewController são, na verdade, as visualizações e não os apresentadores. Essa distinção fornece testabilidade excelente, o que tem o custo da velocidade de desenvolvimento, porque você tem que fazer dados manuais e associação de eventos,

Vejamos os recursos do MVP: Distribuição - temos a maior parte das responsabilidades divididas entre o MVP no iOS significa excelente testabilidade e muito código.

MVP Com Bindings e Hooters Existe outro sabor do MVP - o MVP do Controlador de Supervisão. Esta variante inclui vinculação direta da Visualização e do Modelo enquanto o Apresentador (O Controlador de Supervisão) ainda lida com ações da Visualização e é capaz de alterar a Visualização .

Variante do apresentador de supervisão do MVP Mas, como já aprendemos antes, a separação vaga de responsabilidades é ruim, assim como o acoplamento estreito da Visão e do Modelo . Isso é semelhante a como as coisas funcionam no desenvolvimento de desktop Cocoa. Da mesma forma que com o MVC tradicional, não vejo motivo para escrever um exemplo para a arquitetura falha.

MVVM O mais recente e o melhor do tipo MV (X) O MVVM é o mais novo do tipo MV (X), portanto, esperemos que tenha surgido levando em consideração os problemas que o MV (X) enfrentava anteriormente.

Em teoria, o Model-View-ViewModel parece muito bom. A View e o Model já são familiares para nós, mas também o Mediador, representado como o View Model.

MVVM É muito semelhante ao MVP: o MVVM trata o controlador de visualização como o View Não há um acoplamento forte entre a vista e o modelo Além disso, ele faz ligações como a versão de supervisão do MVP; entretanto, desta vez não entre a vista e o modelo , mas entre a vista e o modelo de vista . Então, qual é o modelo de visualização na realidade do iOS? É basicamente uma representação independente do UIKit de sua Visualização e seu estado. O View Model invoca mudanças no Model e se atualiza com o Model atualizado , e uma vez que temos uma ligação entre View e View

Image

Model , o primeiro é atualizado de acordo. Bindings Mencionei-os brevemente na parte do MVP, mas vamos discuti-los um pouco aqui. As vinculações vêm prontas para o desenvolvimento do OS X, mas não as temos na caixa de ferramentas do iOS. Claro que temos o KVO e as notificações, mas eles não são tão convenientes quanto as ligações. Portanto, desde que não queiramos escrevê-los nós mesmos, temos duas opções: Uma das bibliotecas de ligação baseadas em KVO, como RZDataBinding ou SwiftBond As bestas de programação reativa funcional em escala real , como ReactiveCocoa , RxSwift ou PromiseKit . Na verdade, hoje em dia, se você ouve “MVVM” - você pensa em ReactiveCocoa, e vice-versa. Embora seja possível construir o MVVM com as ligações simples, ReactiveCocoa (ou irmãos) permitirá que você obtenha a maior parte do MVVM. Há uma verdade amarga sobre estruturas reativas: o grande poder vem com a grande responsabilidade. É muito fácil bagunçar as coisas quando você fica reativo . Em outras palavras, se você fizer algo errado, poderá gastar muito tempo depurando o aplicativo, portanto, basta dar uma olhada nesta pilha de chamadas.

Depuração reativa Em nosso exemplo simples, a estrutura FRF ou mesmo o KVO é um exagero. Em vez disso, pediremos explicitamente ao View Model para atualizar usando o método showGreeting e usar a propriedade simples para a função de retorno de chamada greetingDidChange .

Distribuição - não fica claro em nosso pequeno exemplo, mas, na verdade, a visão do MVVM tem mais responsabilidades do que a visão do MVP . Porque o primeiro atualiza seu estado no modelo de exibição configurando ligações, enquanto o segundo apenas encaminha todos os eventos para o apresentador e não se atualiza . Testabilidade - o View Model não sabe nada sobre a View , isso nos permite testá-la facilmente. O modo de exibição também pode ser testado, mas como é dependente do UIKit, você pode querer ignorá-lo.

Fácil de usar - tem a mesma quantidade de código que o MVP em nosso exemplo, mas no aplicativo real, onde você teria que encaminhar todos os eventos da Visualização para o Apresentador e atualizar a Visualização manualmente , o MVVM seria muito mais magro se você usou ligações. O MVVM é muito atraente, pois combina os benefícios das abordagens citadas e, além disso, não requer código extra para as atualizações do View devido aos bindings do lado do View. No entanto, a testabilidade ainda está em um bom nível.

Conceitos do ciclo de Vida da Atividade Android

Para navegar entre as fases do ciclo de vida da atividade, a classe “Activity” fornece um conjunto principal de seis callbacks: onCreate(), onStart(), onResume(), onPause(), onStop() e onDestroy(). Conforme a atividade entra em um novo estado, o sistema invoca cada um desses callbacks.

À medida que o usuário começa a sair da atividade, o sistema chama métodos para eliminá-la. Em alguns casos, essa eliminação é somente parcial. A atividade ainda reside na memória, como quando o usuário alterna para outro aplicativo, e ainda pode voltar ao primeiro plano. Se o usuário retornar a essa atividade, a atividade será retomada de onde o usuário parou. Com algumas exceções, os aplicativos são impedidos de iniciar atividades quando executados em segundo plano.

A probabilidade do sistema eliminar um determinado processo, com as atividades nele, depende do estado da atividade no momento. Em Estado da atividade e ejeção da memória, há mais informações sobre o relacionamento entre o estado e a vulnerabilidade para ejeção.

Dependendo da complexidade de sua atividade, não é necessário implementar todos os métodos do ciclo de vida. No entanto, é importante compreender cada um deles e implementar somente os que garantem que o aplicativo tenha o desempenho esperado pelo usuário.

Image

Os callbacks usados para processar as transições entre os estados.

Callbacks do ciclo de vida Esta seção fornece informações conceituais e de implementação sobre os métodos de callback usados durante o ciclo de vida da atividade.

Algumas ações, como chamar setContentView(), fazem parte dos métodos do ciclo de vida da atividade em si. No entanto, o código que implementa as ações de um componente dependente deve ser colocado no próprio componente. Para fazer isso, você precisa tornar o componente dependente ciente do ciclo de vida. Veja Como gerenciar ciclos de vida com componentes que os reconhecem para saber como tornar seus componentes dependentes cientes do ciclo de vida.

onCreate() Esse callback precisa ser implementado. Ele é acionado assim que o sistema cria a atividade. Quando a atividade é criada, ela insere o estado Criado. No método onCreate(), você executa a lógica básica de inicialização do aplicativo. Isso deve acontecer somente uma vez durante todo o período que a atividade durar. Por exemplo, sua implementação de onCreate() pode vincular dados a listas, associar a atividade a um ViewModel e instanciar algumas variáveis com escopo de classe. Esse método recebe o parâmetro savedInstanceState, um objeto Bundle que contém o estado anteriormente salvo da atividade. Se a atividade nunca existiu, o valor do objeto Bundle será nulo.

Caso você tenha um componente ciente do ciclo de vida conectado ao ciclo de vida da sua atividade, ele receberá o evento ON_CREATE. O método anotado com @OnLifecycleEvent será chamado para que seu componente ciente do ciclo de vida possa executar qualquer código de configuração necessário para o estado criado.

onStart() Quando a atividade insere o estado "Iniciado", o sistema invoca esse callback. A chamada onStart() torna a atividade visível ao usuário, à medida que o aplicativo prepara a atividade para inserir o primeiro plano e se tornar interativa. Por exemplo, é nesse método que o aplicativo inicializa o código que mantém a IU.

Quando a atividade é movida para o estado "Iniciado", qualquer componente ciente do ciclo de vida que esteja ligado ao ciclo de vida da atividade receberá o evento ON_START.

O método onStart() faz a conclusão muito rapidamente e, como no caso do estado "Criado", a atividade não reside no estado "Iniciado". Quando a finalização é feita pelo callback, a atividade insere o estado Retomado e o sistema invoca o método onResume().

onResume() Quando a atividade insere o estado "Retomado", ela vem para o primeiro plano e o sistema invoca o callback onResume(). É nesse estado que o aplicativo interage com o usuário. O app permanece nesse estado até que algo afete o foco do app. Esse evento pode ser, por exemplo, receber uma chamada telefônica, navegar pelo usuário para outra atividade ou desativar a tela do dispositivo.

Quando a atividade é movida para o estado "Retomado", qualquer componente ciente do ciclo de vida ligado ao ciclo de vida da atividade receberá o evento ON_RESUME. É nesse momento que os componentes do ciclo de vida podem ativar qualquer funcionalidade que precise operar enquanto o componente estiver visível e em primeiro plano, como o início da visualização da câmera.

Quando ocorre um evento de interrupção, a atividade insere o estado Pausado e o sistema invoca o callback onPause().

Caso a atividade retorne do estado "Pausado" para o estado "Retomado", o sistema chamará novamente o método onResume(). Dessa forma, implemente o onResume() para inicializar os componentes liberados durante onPause() e execute outras inicializações que devem ocorrer sempre que a atividade entrar no estado "Retomado".

Independentemente de qual evento de construção você escolher para executar uma operação de inicialização, certifique-se de usar o evento de ciclo de vida correspondente para liberar o recurso. Se você inicializar algo após o evento ON_START, libere ou finalize esse item após o evento ON_STOP. Caso você inicialize após o evento ON_RESUME, faça a liberação após o evento ON_PAUSE.

onPause() O sistema chama esse método como a primeira indicação de que o usuário está deixando sua atividade, embora nem sempre signifique que a atividade esteja sendo destruída. Isso indica que a atividade não está mais em primeiro plano, embora ainda possa estar visível se o usuário estiver no modo de várias janelas. Use o método onPause() para pausar ou ajustar operações que não devem continuar (ou que precisem continuar com moderação) enquanto a Activity estiver no modo "Pausado" e aquelas que você espera retomar em breve. Há vários motivos pelos quais uma atividade pode entrar nesse estado. Por exemplo:

Algum evento interromper a execução do aplicativo, conforme descrito na seção onResume(). Esse é o caso mais comum. No Android 7.0 (API de nível 24) ou mais recentes, diversos aplicativos operam no modo de várias janelas. Como só um dos aplicativos (janelas) tem foco a qualquer momento, o sistema pausa todos os outros aplicativos. Uma nova atividade semitransparente (como uma caixa de diálogo) é aberta. Enquanto a atividade estiver parcialmente visível, mas não for a atividade em foco, ela permanecerá pausada. Quando a atividade é movida para o estado pausado, qualquer componente ciente do ciclo de vida ligado ao ciclo de vida da atividade receberá o evento ON_PAUSE. É nesse momento que os componentes do ciclo de vida podem interromper qualquer funcionalidade que não precise operar enquanto o componente não estiver em primeiro plano, como na pausa de uma visualização da câmera.

Também é possível usar o método onPause() para liberar recursos do sistema, tratamento de sensores (como GPS) ou quaisquer recursos que possam afetar a duração da bateria enquanto a atividade estiver pausada e o usuário não precisar deles. No entanto, como mencionado acima, na seção onResume(), uma atividade pausada ainda poderá ser completamente visível no modo de várias janelas. Assim, considere usar onStop() em vez de onPause() para liberar ou ajustar completamente operações e recursos relacionados à IU para melhorar o suporte do modo de várias janelas.

A conclusão do método onPause() não significa que a atividade saia do estado "Pausado". Na verdade, a atividade permanece nesse estado até que ela seja retomada ou fique completamente invisível para o usuário. Se a atividade for retomada, o sistema invocará mais uma vez o callback onResume(). Caso a atividade retorne do estado "Pausado" para o estado "Retomado", o sistema manterá a instância Activity residente na memória, chamando novamente a instância quando o sistema invocar onResume(). Nesse cenário, não é necessário reiniciar componentes criados durante qualquer método de callback que leve ao estado "Retomado". Se a atividade ficar completamente invisível, o sistema chamará onStop(). A próxima seção discutirá o callback onStop().

onStop() Quando a atividade não estiver mais visível ao usuário, ela inserirá o estado Interrompido e o sistema invocará o callback onStop(). Isso pode ocorrer, por exemplo, quando uma atividade recém-iniciada preenche toda a tela. O sistema também poderá chamar onStop() quando a atividade parar de operar e estiver prestes a ser concluída.

Quando a atividade é movida para o estado interrompido, qualquer componente ciente do ciclo de vida ligado ao ciclo de vida da atividade receberá o evento ON_STOP. É nesse momento que os componentes do ciclo de vida podem interromper qualquer funcionalidade que não precise operar enquanto o componente não estiver visível na tela.

No método onStop(), o aplicativo liberará ou ajustará recursos desnecessários enquanto o aplicativo não estiver visível ao usuário. Por exemplo, o aplicativo poderá pausar animações ou alternar de atualizações de local mais específicas para as menos detalhadas. O uso de onStop() em vez de onPause() garante que o trabalho relacionado à IU continue, mesmo quando o usuário estiver visualizando a atividade no modo de várias janelas.

Use onStop() também para realizar operações de desligamento de uso intensivo da CPU. Por exemplo, se você não encontrar um momento mais oportuno para salvar informações em um banco de dados, poderá fazer isso durante onStop().

Fonte(s): Google Android Developers

Ciclo de vida da atividade Android

Pode parecer estranho, mas a forma que eu posto conteúdo não segue a ordem lógica do aprendizado, aviso caso não esteja acostumado com meus posts ;)

A ideia aqui e falar um pouco sobre o ciclo de vida da atividade do Android. Nada que você não encontre igual na documentação do Android.

Conforme o usuário navega pelo aplicativo, sai dele e retorna a ele, as instâncias Activity no aplicativo transitam entre diferentes estados no ciclo de vida.

A classe Activity fornece uma quantidade de callbacks que permite rastrear essas atividades.

Dentro dos métodos de callback do ciclo de vida, você pode declarar como a atividade deve se comportar quando o usuário sai e retorna dela.

Image

Por exemplo, se estiver construindo um reprodutor de vídeos de transmissão em sequência, você pode pausar o vídeo e encerrar a conexão da rede quando o usuário alternar para outro aplicativo. Quando o usuário retornar, será possível reconectar a rede e permitir que ele reinicie o vídeo de onde parou. Ou seja, cada callback permite que você realize o trabalho específico adequado a determinada mudança de estado.

Fazer o trabalho certo no momento apropriado e gerenciar as transições da maneira correta faz com que seu aplicativo seja mais robusto e tenha melhor desempenho.

Por exemplo, uma boa implementação dos callbacks de ciclo de vida pode ajudar a garantir que seu aplicativo evite os problemas a seguir:

  • Falhas se o usuário receber uma chamada telefônica ou mudar para outro aplicativo enquanto estiver usando seu aplicativo.
  • Consumo de recursos importantes do sistema quando o usuário não estiver usando ativamente o aplicativo.
  • Perda do progresso do usuário se ele sair do aplicativo e retornar mais tarde. *Falhas ou perda do progresso do usuário quando a orientação da tela mudar entre paisagem e retrato.

A ideia é entender o que acontece internamente quando operam e o que você deve implementar durante a execução deles.

Fonte(s): Google Android Developers