Projeto: app Lemonade

Este codelab apresenta um novo app, chamado Lemonade, que você criará por conta própria. O codelab mostra os passos para concluir o projeto, incluindo a configuração e os testes no Android Studio.

Este codelab é diferente dos outros deste curso. Ao contrário dos codelabs anteriores, o objetivo deste codelab não é fornecer um tutorial passo a passo sobre como criar um app. O objetivo deste codelab é configurar um projeto que será concluído de forma independente, com instruções sobre como concluir o app e verificar seu trabalho por conta própria.

Em vez do código da solução, fornecemos um conjunto de testes como parte do download do app. Você executará esses testes no Android Studio (mostraremos como fazer isso posteriormente neste codelab) e veremos se o código é aprovado. Isso pode levar algumas tentativas. Até mesmo desenvolvedores profissionais raramente passam em todos os testes na primeira vez. Depois que seu código passar em todos os testes, considere o projeto como concluído.

Entendemos que talvez você queira apenas uma solução para conferir seu trabalho. Não fornecemos o código da solução deliberadamente, porque queremos que você pratique como é ser um desenvolvedor profissional. Isso pode exigir o uso de diferentes habilidades que você ainda não tem prática, como:

  • pesquisar no Google os termos, mensagens de erro e códigos do app que você não reconhece;
  • testar o código, ler erros e fazer mudanças no código para testá-lo novamente;
  • voltar ao conteúdo anterior da Unidade 1 de noções básicas do Android para conferir o que você aprendeu;
  • comparar um código conhecido (ou seja, o código fornecido no projeto ou o código anterior da solução em outros apps da Unidade 1) com o código que você está escrevendo.

Isso pode parecer complicado no início, mas temos 100% de certeza de que, se você concluiu a Unidade 1, já pode começar o projeto. Leve o tempo que precisar e não desista. Você consegue.

Pré-requisitos

  • Este projeto é destinado para usuários que concluíram a Unidade 1 do curso Princípios básicos do Android em Kotlin.

O que você criará

  • Você criará um app Lemonade simples usando as habilidades que aprendeu na Unidade 1.

Pré-requisitos

  • Um computador com o Android Studio instalado

Bem-vindo ao projeto do app Lemonade.

Você foi recrutado para nossa equipe a fim de nos ajudar a realizar nosso sonho de criar uma limonada digital. O objetivo é criar um app para dispositivos móveis simples e interativo que permita espremer limões até ter um copo de limonada. Considere isso uma metáfora ou apenas uma forma divertida de passar o tempo.

O app Lemonade concluído terá uma única tela. Quando os usuários iniciarem o app pela primeira vez, eles receberão uma solicitação para escolher um limão tocando na imagem de um limoeiro.

d61077d38ce788da.png

Ao tocar no limoeiro, o usuário verá um limão e poderá tocar nele para o "espremer" um número não especificado de vezes (o número exato necessário é gerado aleatoriamente) antes de passar para a próxima tela.

c4897dc7432c2908.png

Depois que o usuário tocar para espremer o limão o número certo de vezes, ele verá a imagem de um copo para "tomar" a limonada.

846dd7e1b8c230c.png

Depois de clicar para beber a limonada, o copo ficará vazio e o usuário poderá tocar na imagem novamente para retornar à primeira tela e selecionar outro limão na árvore.

9dfc622d3c2efee7.png

O app foi criado com foco em simplicidade e organizado em uma única atividade. Os diferentes estados do app (se o usuário está selecionando um limão, o espremendo, bebendo limonada e, finalmente, o copo vazio) são representados por algo conhecido como máquina de estado. Parece um termo teórico sofisticado, mas significa que o estado do app, ou seja, qual texto e imagem serão mostrados ao usuário, é determinado por uma variável que contém o estado do app (select, squeeze etc.). O estado do app é atualizado, com outras variáveis necessárias, e a IU é configurada (exibindo a imagem e o texto) separadamente, assim que todas as atualizações são feitas.

Todas as variáveis para o estado do app foram definidas para você. Sua tarefa é criar o layout do app e implementar a lógica para que a IU faça a transição entre cada estado conforme o esperado.

Testar o código

Para o app Lemonade (e projetos futuros), são fornecidos alguns testes automatizados que podem ser usados para verificar se o código funciona como esperado.

O que são testes automatizados? Em termos de desenvolvimento de software, pense em um "teste" como um código que verifica se outro código está funcionando. Isso é feito verificando as saídas, por exemplo, o conteúdo dos elementos da IU na tela, para ver se elas fazem sentido com base nas entradas, conhecidas como "casos de teste". O projeto inicial do app Lemonade inclui alguns testes que você poderá executar para garantir que a lógica foi implementada corretamente. Discutiremos os testes em mais detalhes posteriormente. Por enquanto, faça o download do código inicial e comece a criar o app Lemonade.

Fazer o download do código do projeto

O nome da pasta é android-basics-kotlin-lemonade-app. Selecione essa pasta ao abrir o projeto no Android Studio.

Para encontrar o código deste codelab e abri-lo no Android Studio, faça o seguinte.

Buscar o código

  1. Clique no URL fornecido. Isso abrirá a página do GitHub referente ao projeto em um navegador.
  2. Na página do GitHub do projeto, clique no botão Code, que exibirá uma caixa de diálogo.

5b0a76c50478a73f.png

  1. Na caixa de diálogo, clique no botão Download ZIP para salvar o projeto no seu computador. Aguarde a conclusão do download.
  2. Localize o arquivo no computador, que provavelmente está na pasta Downloads.
  3. Clique duas vezes no arquivo ZIP para descompactá-lo. Isso criará uma nova pasta com os arquivos do projeto.

Abrir o projeto no Android Studio

  1. Inicie o Android Studio.
  2. Na janela Welcome to Android Studio, clique em Open an existing Android Studio project.

36cc44fcf0f89a1d.png

Observação: caso o Android Studio já esteja aberto, selecione a opção File > New > Import Project.

21f3eec988dcfbe9.png

  1. Na caixa de diálogo Import Project, vá até a pasta do projeto descompactada, que provavelmente está na pasta Downloads.
  2. Clique duas vezes nessa pasta do projeto.
  3. Aguarde o Android Studio abrir o projeto.
  4. Clique no botão Run 11c34fc5e516fb1c.png para criar e executar o app. Confira se ele é compilado da forma esperada.
  5. Procure os arquivos do projeto na janela de ferramentas Project para ver como o app está configurado.

Reserve um momento para se familiarizar com o projeto inicial. Preste atenção especial ao arquivo MainActivity.kt.

187e261ddee1b032.png

No MainActivity.kt, você encontrará diversas variáveis usadas para representar o estado atual do app. Elas serão usadas em uma etapa posterior para tornar o app interativo. Embora a quantidade de código aqui possa parecer complexa, não é necessário modificar nenhum código que não esteja marcado com TODO. Instruções específicas são fornecidas nas páginas a seguir.

Observe que o projeto também inclui outro pacote, com.example.lemonade (androidTest).

d68e0812be53370d.png

Esse pacote inclui os testes automatizados que você usará para verificar se a funcionalidade que implementou em MainActivity.kt está correta. Mais detalhes serão explicados posteriormente. Por enquanto, está tudo pronto para você começar a criar o app, começando com a interface do usuário.

O app Lemonade precisa de um layout básico. Você só precisa de duas visualizações para implementar todas as funcionalidades.

  1. Uma TextView que fornece instruções ao usuário.
  2. Uma ImageView que mostra um gráfico com base no estado atual do app (por exemplo: um limão para ser espremido).

Você criará esse layout em activity_main.xml.

da9d7b9e9e85b339.png

Usando seus conhecimentos sobre o Layout Editor, o objetivo é criar um layout semelhante ao exemplo abaixo, com as visualizações centralizadas na tela e a TextView acima da ImageView.

d384c5cc4d7b5634.png

Quando o layout estiver concluído, abra MainActivity.kt. É neste arquivo em que você implementará toda a lógica do app. Você perceberá que ele já tem bastante código. Há também muitos comentários marcados com // TODO:, como no exemplo abaixo. Os comentários marcam as tarefas que você irá concluir.

d3a4d509918df93c.png

Existem três coisas básicas que você precisa implementar para que o app Lemonade funcione.

  1. Configurar a lemonImage da ImageView para responder à entrada do usuário.
  2. Implementar o método clickLemonImage() para atualizar o estado do app.
  3. Implementar o método setViewElements() para atualizar a IU com base no estado atual do app.

Vamos analisar uma tarefa por vez.

Etapa 1: configurar a ImageView

Tocar na visualização da imagem precisa mover o app de um estado para outro. No final do método onCreate(), observe que há dois listeners que precisam ser definidos.

  1. setOnClickListener() precisa atualizar o estado do app. O método para fazer isso é clickLemonImage().
  2. setOnLongClickListener() responde a eventos em que o usuário toca em uma imagem e a mantém pressionada, por exemplo, toca na imagem e não solta o dedo imediatamente. Para eventos de "tocar e manter pressionado", um widget, chamado de "snackbar", é exibido na parte inferior da tela. Nela, o usuário saberá quantas vezes ele espremeu o limão. Isso é feito usando o método showSnackbar().

54f9f0a3aa903c31.png

Na próxima etapa, você implementará a lógica para alterar o estado do app.

Etapa 2: implementar clickLemonImage()

Depois de concluir a etapa anterior, o método clickLemonImage() será chamado sempre que o usuário tocar na imagem. Esse método é responsável por passar o app do estado atual para o próximo e atualizar as variáveis conforme necessário. Há quatro estados possíveis: SELECT, SQUEEZE, DRINK e RESTART. O estado atual é representado pela variável lemonadeState. Esse método precisa fazer algo diferente para cada estado.

  1. SELECT: muda para o estado SQUEEZE, define lemonSize (o número de espremidas necessárias) chamando o método pick() e definindo squeezeCount (o número de vezes que o usuário espremeu o limão) como 0.
  2. SQUEEZE: incrementa a squeezeCount em 1 e reduz o lemonSize em 1. Lembre-se de que um limão exigirá um número variável de espremidas squeezeCount antes de ser totalmente espremido. Mude para o estado DRINK somente se o novo lemonSize for igual a 0. Caso contrário, o app permanecerá no estado SQUEEZE.
  3. DRINK: muda para o estado RESTART e define lemonSize como -1.
  4. RESTART: volta para o estado SELECT.

Depois de processar todas as atualizações e transições entre estados, chame setViewElements() para atualizar a IU com base no novo estado.

Etapa 3: implementar setViewElements()

O método setViewElements() é responsável por atualizar a IU com base no estado do app. O texto e a imagem precisam ser atualizados com os valores mostrados abaixo para corresponder a lemonadeState.

SELECT:

  • Texto: Click to select a lemon!
  • Imagem: R.drawable.lemon_tree

SQUEEZE:

  • Texto: Click to juice the lemon!
  • Imagem: R.drawable.lemon_squeeze

DRINK:

  • Texto: Click to drink your lemonade!
  • Imagem: R.drawable.lemon_drink

RESTART:

  • Texto: Click to start again!
  • Imagem: R.drawable.lemon_restart

Como usar recursos de string

No Android, quase tudo é um recurso. Definir recursos que você pode acessar no app é uma parte essencial do desenvolvimento para Android.

Os recursos são usados para qualquer ação, desde a definição de cores, imagens, layouts, menus e valores de strings. A vantagem disso é que nada é fixado no código. Todos os elementos são definidos nesses arquivos de recursos e, em seguida, podem ser referenciados no código do aplicativo. O mais simples dos recursos, e o mais comum, é usar recursos de string para permitir um texto flexível e localizado.

Strings ou texto estático podem ser armazenados em um arquivo separado, chamado "strings.xml", na subpasta de valores da pasta "res".

65588c6102e5139.png

Para cada trecho do texto que você quer exibir no aplicativo (por exemplo, o rótulo de um botão ou o texto de uma TextView), primeiro defina o texto no arquivo res/values/strings.xml. Cada entrada é uma chave (que representa o código do texto) e um valor (o texto em si). Por exemplo, se você quiser que um botão exiba "Submit" (Enviar), adicione o recurso de string a seguir em res/values/strings.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello!</string>
    <string name="submit_label">Submit</string>
</resources>

Para acessar o recurso diretamente no código, use os métodos getResources.getString() ou getString() para acessar o valor considerando o ID do recurso, R.string.submit_label:

val submitText = getResources().getString(R.string.submit_label)

Para definir diretamente o texto do recurso de string para a TextView, chame o método setText() no objeto da TextView e transmita o ID do recurso.

val infoTextView: TextView = findViewById(R.id.info_textview)

infoTextView.setText(R.string.info_text)

Os recursos de string também podem conter caracteres especiais para formatar o texto. Por exemplo, você pode ter um recurso de string que permite inserir outro trecho de texto na string:

<string name="ingredient_tablespoon">%1$d tbsp of %2$s</string>

No código, você acessaria e formataria o recurso da string transmitindo argumentos:

getResources().getString(R.string.ingredient_tablespoon, 2, "cocoa powder")

Ao declarar o recurso da string, cada argumento é numerado na ordem em que aparece (1, 2 etc.) e tem uma letra para identificar o tipo (d para números decimais, s para string etc.). Argumentos do tipo correto podem ser transmitidos para a chamada do método getString():

2 tbsp of cocoa powder

Para saber mais, consulte a documentação sobre recursos de string.

Depois de criar a IU do app e implementar a atividade principal, é hora de ver seu trabalho em ação. Execute o app usando o menu Run > Run 'app', para iniciar o emulador.

ae484ede4fe1dd1f.png

Agora, o app precisa estar totalmente interativo, e você pode tocar na visualização da imagem para mudar os estados.

3e8867f3aea54c78.png

Enquanto o limão estiver na tela, você também poderá tentar tocar na ImageView e a manter pressionada para ver a snackbar na parte inferior, revelando o número total de vezes que o limão foi espremido. Passe um tempo para percorrendo o app em todos os estados algumas vezes. Em seguida, passe um tempo comemorando os resultados do seu esforço.

Testar o app

Você terminou de implementar o app Lemonade, mas, no desenvolvimento de software profissional, criar o código raramente é a última etapa. Além do código do aplicativo, apps de qualidade profissional também incluem códigos de teste que são executados para verificar se o código funciona conforme o esperado e se alterações nele não introduzem novos bugs, um processo chamado de "teste automatizado". Embora o ensino de testes automatizados esteja além do escopo deste projeto, o app Lemonade vem com alguns testes que ajudam a verificar se você o implementou corretamente. Use-os como uma autoavaliação para ver se atendeu a todos os requisitos do projeto e se é necessário fazer mudanças no app.

O que é um "teste" exatamente? Os testes são partes do código incluído no projeto do Android Studio que executam parte do código do app e podem ser "aprovados" ou "reprovados", dependendo do código do app ter o comportamento esperado ou não.

Onde você encontra e executa os testes do app? Os testes do app Lemonade estão disponíveis no destino de teste. Um destino é um termo de desenvolvimento de software para uma coleção de classes agrupadas. Por exemplo, o app Lemonade existe em um destino chamado "app", enquanto os testes existem em um destino chamado "LemonadeTests". Embora o destino LemonadeTests possa acessar o código do destino do app, eles são completamente separados, e o código do app não contém nenhum código de teste.

20edcb90dca9d70b.png

Ao visualizar os arquivos na visualização "Android", o destino do teste será exibido com o mesmo nome de pacote do app, mas com (androidTest) entre parênteses.

Também há alguns termos importantes que você precisa conhecer ao se referir ao código de teste.

  • Pacote de testes: o destino que inclui todos os casos de teste.
  • Caso de teste: uma classe que consiste em testes individuais de funcionalidades relacionadas. O app Lemonade tinha apenas um único caso, mas os apps maiores muitas vezes têm muito mais.
  • Teste: uma função que testa algo específico.

Um caso de teste pode ter vários testes e o conjunto de testes do projeto pode ter vários casos de teste.

Como executar os testes

Para executar os testes, escolha uma das opções a seguir.

Para um único caso de teste, abra uma classe de caso de teste e clique na seta verde à esquerda da declaração da classe. Em seguida, selecione a opção "Run" no menu. Isso executará todos os testes do caso.

a32317d35c77142b.png

Na maioria das vezes, convém executar apenas um teste, por exemplo, se apenas um teste for reprovado e os outros forem aprovados. Você pode executar um único teste da mesma forma que faria com todo o caso de teste. Use a seta verde e selecione a opção Run.

ac6244434cfafb60.png

Se você tiver vários casos de teste, também poderá executar todo o conjunto de testes. Assim como na execução do app, você encontra essa opção no menu Run.

7a925c5e196725bb.png

O Android Studio usará como padrão o último destino que você executou (app, destinos de teste etc.). Portanto, se o menu ainda exibir Run > Run 'app', você poderá executar o destino de teste selecionando Run > Run.

ee1e227446c536fe.png

Em seguida, escolha o destino do teste no menu pop-up.

d570c947769db65c.png

Os resultados da execução dos testes serão exibidos na guia Run. No painel à esquerda, você verá uma lista de testes reprovados, se houver algum. Os testes reprovados são marcados com um ponto de exclamação vermelho ao lado do nome da função. Os testes aprovados são marcados com uma marca de seleção verde.

6d68f2bf589501ae.png

Se um teste for reprovado, o texto do resultado fornecerá informações para ajudar você a corrigir o problema.

92f3c8219c03651d.png

Por exemplo, na mensagem de erro acima, o teste verifica se um TextView está usando um recurso de string específico. No entanto, o teste é reprovado. O texto após "Expected" e "Got" não coincide, ou seja, o valor esperado para o teste não corresponde ao valor do app em execução. Nesse exemplo, a string usada na TextView não é squeeze_count, como esperado no teste.

Quando terminar de tomar vários copos de limonada, faça uma captura da sua tela favorita e a compartilhe no Twitter para mostrar o que você aprendeu. Marque @AndroidDev e adicione a hashtag #AndroidBasics.