Escolar Documentos
Profissional Documentos
Cultura Documentos
de Aplicativos para
Dispositivos Móveis
RAFAEL MUNHOZ ALMEIDA DA SILVA
Editora
SÃO PAULO/ SP
DESENVOLVIMENTO DE
A P L I C AT I V O S PA R A
DISPOSITIVOS MÓVEIS
Editora:
Editora
EXPEDIENTE
AUTOR(ES) COORDENAÇÃO,
PROJETO GRÁFICO E CAPA
Rafael Munhoz Almeida da
Silva João Guedes
Editora
Apresentação
Prezado Aluno,
V
ivemos na era dos aplicativos para dispositivos mó-
veis, hoje em dia os dispositivos móveis são muito
acessíveis economicamente e a maioria da popula-
ção possui pelo menos um destes dispositivos, o que gera
uma demanda muito alta do mercado por profissionais com
a habilidade de desenvolver este tipo de software.
Neste livro você vai entrar em contato com o desenvolvi-
mento de aplicativos para dispositivos móveis utilizando a
plataforma Android. Você verá como instalar o ambiente de
desenvolvimento oficial do Android que é o Android Studio.
Terá uma introdução sobre a nova linguagem oficial de
programação chamada Kotlin, aprenderá a usar o editor
de layout para construir interfaces gráficas e ao longo do
material irá desenvolver dois aplicativos.
Portanto desejo a você estudante, uma ótima leitura, e
que você se divirta ao conhecer um pedacinho deste enorme
mundo que é o de desenvolvimento de aplicativos para dis-
positivos móveis.
Bons Estudos!
4
SUMÁRIO:
UNIDADE 1:
PROGRAMANDO PARA O ANDROID���������������������������������1-1
CAPÍTULO 1:
INTRODUÇÃO AO ANDROID��������������������������������������������� 1-2
EXERCÍCIOS PROPOSTOS������������������������������������������������� 1-10
CAPÍTULO 2:
INTRODUÇÃO AO ANDROID STUDIO������������������������������������ 2-1
EXERCÍCIOS PROPOSTOS������������������������������������������������� 2-11
UNIDADE 2:
INTRODUÇÃO A LINGUAGEM KOTLIN�������������������������������3-1
CAPÍTULO 3:
VARIÁVEIS, TIPOS E OPERADORES������������������������������������ 3-2
EXERCÍCIOS PROPOSTOS������������������������������������������������� 3-21
CAPÍTULO 4:
CONTROLE DE FLUXO��������������������������������������������������� 4-1
EXERCÍCIOS PROPOSTOS������������������������������������������������� 4-12
UNIDADE 3:
APROFUNDANDO NA LINGUAGEM KOTLIN�������������������������5-1
CAPÍTULO 5:
LISTAS E FUNÇÕES������������������������������������������������������ 5-2
EXERCÍCIOS PROPOSTOS������������������������������������������������� 5-13
CAPÍTULO 6:
CLASSES������������������������������������������������������������������ 6-1
EXERCÍCIOS PROPOSTOS������������������������������������������������� 6-17
UNIDADE 4:
PRIMEIRO APLICATIVO: ÁLCOOL OU GASOLINA�������������������7-1
CAPÍTULO 7:
DEFININDO O LAYOUT��������������������������������������������������� 7-2
EXERCÍCIOS PROPOSTOS������������������������������������������������� 7-13
CAPÍTULO 8:
CODIFICANDO A ACTIVITY���������������������������������������������� 8-1
EXERCÍCIOS PROPOSTOS������������������������������������������������� 8-15
UNIDADE 5:
SEGUNDO APLICATIVO: LISTA DE COMPRAS����������������������9-1
CAPÍTULO 9:
RECYCLERVIEW E RECYCLERADAPTER������������������������������� 9-2
EXERCÍCIOS PROPOSTOS������������������������������������������������� 9-31
CAPÍTULO 10:
VISUALIZANDO E ADICIONANDO ITENS������������������������������ 10-1
EXERCÍCIOS PROPOSTOS������������������������������������������������ 10-26
UNIDADE 6:
PERSISTÊNCIA NO APLICATIVO LISTA DE COMPRAS����������� 11-1
CAPÍTULO 11:
CRIANDO A CAMADA DE PERSISTÊNCIA���������������������������� 11-2
EXERCÍCIOS PROPOSTOS������������������������������������������������ 11-12
CAPÍTULO 12:
INTEGRANDO A CAMADA DE PERSISTÊNCIA����������������������� 12-1
EXERCÍCIOS PROPOSTOS������������������������������������������������ 12-17
REFERÊNCIAS��������������������������������������������������������� 13-1
GABARITO������������������������������������������������������������� 14-1
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
UNIDADE 1:
PROGRAMANDO PARA O ANDROID
Caro(a) Aluno(a)
Seja bem-vindo(a)!
Ótimos estudos!
Conteúdos da Unidade:
Evolução do sistema operacional Android, Visão geral da ar-
quitetura, Instalação do ambiente de desenvolvimento oficial,
Desenvolvimento do projeto Hello World.
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
CAPÍTULO 1:
INTRODUÇÃO AO ANDROID
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 1
IN TR O D U Ç ÃO AO AN D R O I D
1.1 O sistema operacional Android
No início dos anos 2000, os celulares estavam começando a
se popularizar, o tamanho dos aparelhos estava diminuindo, ou-
tras funcionalidades estavam sendo embarcadas nos aparelhos,
tais como agendas eletrônicas e até mesmo jogos.
Com o aumento da produção o custo dos aparelhos começou
a diminuir tornando o celular um dispositivo acessível a uma boa
parte da população.
Porém cada fabricante possuía o seu próprio sistema embar-
cado, ou seja, um aplicativo desenvolvido para um celular de um
determinado fabricante não seria compatível com outro dispositi-
vo de outro fabricante.
Ou seja, para que um aplicativo funcionasse em vários dispo-
sitivos ele teria que ser reescrito e recompilado, gerando custo de
desenvolvimento e manutenção.
Já prevendo que o smartphone nasceria em breve o primeiro
sistema operacional comum foi criado. Este sistema é o Symbian,
que possuía código fechado, os aplicativos escritos para ele deve-
riam usar a linguagem C++.
Alguns anos mais tarde nasce o Android, que é um sistema
operacional aberto, ou seja, os fabricantes poderiam customizá-lo,
diferente do Symbian que era fechado.
Os aplicativos para o sistema operacional Android podem ser
escritos em C++ e Java.
Existem várias teorias que descrevem o sucesso do Android
sobre o Symbiam, algumas dizem que o Android foi mais aceito
pois era mais fácil de desenvolver aplicativos, pois o framework,
1-3
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 1
IN TR O D U Ç ÃO AO AN D R O I D
que são as ferramentas que usamos para fazer campos de texto,
tablets etc, eram mais fáceis de entender.
E na época a linguagem Java tinha uma curva de aprendiza-
do bem menor que a linguagem C++.
Algumas teorias afirmam que o Android, por ser um sistema
operacional de código fonte aberto, ou seja, por poder ser custo-
mizado pelos fabricantes foi mais bem aceito e se espalhou pela
maioria deles.
Quando o Android foi lançado para uso público, ele já pos-
suía todo um ecossistema para a distribuição dos aplicativos, ou
seja, era muito mais fácil encontrar e instalar aplicativos para os
dispositivos baseados em Android do que para os dispositivos
Symbian, alguns analistas dizem que esse foi o principal fator que
fez do Android o sistema operacional mais popular para dispositi-
vos móveis.
1-4
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 1
IN TR O D U Ç ÃO AO AN D R O I D
Versão Apelido Lançamento API
8.1 15 de dezembro de 2017 27
Oreo
8.0 21 de agosto de 2017 26
7.1.x 5 de dezembro de 2016 25
Nougat
7.0.x 22 de agosto de 2016 24
6.0.-6.0.1 Marshmallow 05 de Outubro de 2015 23
5.1-5.1.1 10 de março de 2015 22
Lollipop
5.0-5.0.2 12 de novembro de 2014 21
4.4-4.4.4 KitKat 31 de outubro de 2013 19
4.3.x 24 de julho de 2013 18
4.2.x Jelly Bean 13 de novembro de 2012 17
4.1.x 9 de julho de 2012 16
4.0.3–4.0.4 Ice Cream Sandwich 16 de dezembro de 2011 15
2.3.3–2.3.7 Gingerbread 9 de fevereiro de 2011 10
2.2-2.2.3 Froyo 20 de maio de 2010 8
2.0-2.1 Eclair 26 de outubro de 2009 5
1.6 Donut 15 de setembro de 2009 4
1.5 Cupcake 27 de abril de 2009 2
1.0-1.1 Petit Four ou Beta 23 de setembro de 2008 1
Fonte: https://pt.wikipedia.org/wiki/Android
1-5
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 1
IN TR O D U Ç ÃO AO AN D R O I D
1-6
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 1
IN TR O D U Ç ÃO AO AN D R O I D
1.2.1 System Apps
Nesta camada encontraremos os aplicativos tais como o
Dialer (Aplicativo de telefone), aplicativo de e-mail,
aplicativo de calendário entre outros.
Como o Android possui o código fonte aberto, podemos
modificar estes aplicativos para satisfazer as necessidades de um
determinado fabricante, como por exemplo podemos modificar o
aplicativo de telefone para que ele recuse chamadas de números
considerados indesejáveis.
1-7
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 1
IN TR O D U Ç ÃO AO AN D R O I D
A biblioteca Webkit utilizada no processamento de páginas
html, código javascript entre outras funcionalidades de um
browser de internet.
As bibliotecas desta camada também podem ser acessadas
por meio da linguagem Java, na camada Java API Framework.
A Android Runtime (ART) é a máquina virtual que processa
o bytecode do Java/Kotlin. Quando um aplicativo é compi-
lado para a plataforma Android, tanto na linguagem Java quanto
na linguagem Kotlin, teremos como produto um arquivo do tipo
.DEX é neste arquivo que teremos o bytecode do código que será
lido pela ART.
Podemos também desenvolver aplicativos nativos para esta
camada utilizando o Android NDK, ou seja, podemos escrever di-
retamente código C++ que será compilado pelo NDK.
1-8
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 1
IN TR O D U Ç ÃO AO AN D R O I D
operacional como gerenciamento de memória, controle de proces-
sos entre outras.
É nesta camada que os fabricantes também desenvolvem
os drivers específicos para o hardware dos dispositivos. Como
por exemplo um fabricante desenvolve um telefone novo, com um
novo controlador de rede, é na camada do kernel que ele vai imple-
mentar o novo driver para este novo hardware.
1-9
EXERCÍCIOS PROPOSTOS
1-10
o Android superou o Symbian pois seus aplicativos eram es-
critos em java.
EX ER C ÍC IO S PR O PO STO S
( ) -c) O Android superou o Symbian por possuir um framework
completo com muitos elementos gráficos e outras bibliote-
cas como conexão de rede, acesso ao sistema de arquivos,
além de ser de código aberto e de possuir um ecossistema
completo para o download de aplicativos.
( ) -d) O Android superou o Symbian apenas por possibilitar o de-
senvolvimento dos aplicativos usando a linguagem Java.
( ) -e) Nda.
1-11
6) Quando criamos um aplicativo de lista de compra, para a plataforma
EX ER C ÍC IO S PR O PO STO S
Android escrito nas linguagens Java ou Kotlin, em qual camada este apli-
cativo pode ser classificado:
1-12
8) Sobre a Android Runtime (ART) escolha a alternativa verdadeira.
EX ER C ÍC IO S PR O PO STO S
( ) -a) A Android Runtime fica na camada JAVA API Framework
pois é a máquina virtual que executa os aplicativos compila-
dos em Java ou Kotlin.
( ) -b) A Android Runtime fica no mesmo nível da camada Native
C/C++ e é responsável por executar o código compilado dos
aplicativos escritos em Java ou Kotlin.
( ) -c) A Android Runtime executa apenas código compilado que
foi escrito na linguagem C/C++
( ) -d) A Android Runtime não acessa as bibliotecas escritas em C/
C++
( ) -e) A Android Runtime não processa arquivos do tipo .DEX
10) Qual camada fornece uma abstração para o acesso do hardware que con-
trola a câmera de um dispositivo.
1-13
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
CAPÍTULO 2:
INTRODUÇÃO AO ANDROID STUDIO
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 2
IN TR O D U Ç Ã O A O A N D R O ID ST U D I O
2.1 Instalando e utilizando o Android Studio
No início a plataforma Android não possuia uma IDE (In-
tegrated Development Environment), ou seja, cabia ao de-
senvolvedor baixar todas as ferramentas necessárias, tais como o
Java, o SDK do Android, o Emulador do Android, e alguma outra
ferramenta que integrava todas essas, geralmente era utilizado o
Eclipse com um plugin para o desenvolvimento Android.
Isso tudo mudou quando o Android Studio foi criado, basea-
do no IntelliJ, o Android Studio baixa automaticamente todas
as ferramentas necessárias para o desenvolvimento de aplicati-
vos Android.
O Android Studio pode ser instalado nos sistemas operacio-
nais Windows, Mac OS e Linux, para isso acesse o link https://
developer.android.com/studio e baixe o executável de instalação
do sistema operacional que você está utilizando e siga os passos
da instalação.
Quando a instalação terminar, execute o aplicativo do An-
droid Studio, você deverá ver algo similar a figura abaixo no mo-
mento da execução:
2-2
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 2
IN TR O D U Ç Ã O A O A N D R O ID ST U D I O
Figura 2-1: Android Studio
2-3
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 2
IN TR O D U Ç Ã O A O A N D R O ID ST U D I O
Figura 2-2: Criando novo projeto
2-4
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 2
IN TR O D U Ç Ã O A O A N D R O ID ST U D I O
ser escritos em C++ e Java, porém desde 2017 a linguagem Kotlin
foi anunciada como sendo a linguagem oficial do Android, por isso
vamos deixar o campo Language com o valor Kotlin. Falaremos
muito mais sobre a linguagem Kotlin nos próximos capítulos.
Por fim, vamos usar como SDK mínimo a API 21, portanto
basta deixar o campo Minimum SDK com esse valor ou modificá-lo
caso este não seja o seu valor.
Depois de revisarmos todas estas informações podemos cli-
car no botão Finish, para que o Android Studio crie o esqueleto
da nossa primeira aplicação.
2-5
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 2
IN TR O D U Ç Ã O A O A N D R O ID ST U D I O
2.1.2 Conhecendo o Android Studio
Quando clicamos no botão Finish, o Android Studio nos
leva para tela de projeto, perceba que basicamente esta tela é divi-
dida em duas grandes partes, do lado esquerdo temos o navegador
de projeto, por meio dessa interface podemos navegar pelos arqui-
vos do projeto.
Do lado direito será mostrado o conteúdo de um arquivo que
foi selecionado do lado esquerdo. A figura abaixo mostra a tela do
Android Studio.
2-6
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 2
IN TR O D U Ç Ã O A O A N D R O ID ST U D I O
os arquivos que implementam a sua lógica, os recursos gráficos
como layout de tela e imagens etc.
Bem no final temos a pasta Gradle Scritps, o Gradle é
um gerenciador de construção e de bibliotecas utilizado no Android
Studio e nessa pasta temos os arquivos que fazem a sua configuração.
1| package com.munhra.olamundo
2|
3| import androidx.appcompat.app.
AppCompatActivity
4| import android.os.Bundle
5|
6| class MainActivity : AppCompatActivity() {
7|
override fun onCreate(savedInstanceS-
tate: Bundle?) {
8|
super.onCreate(savedInstanceState)
2-7
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 2
IN TR O D U Ç Ã O A O A N D R O ID ST U D I O
9|
setContentView(R.layout.
activity_main)
10| }
11| }
2-8
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 2
IN TR O D U Ç Ã O A O A N D R O ID ST U D I O
da classe MainActivity, este método é responsável por de-
senhar os elementos da tela que estão definidos no parâmetro
R.layout.activity_main.
Este parâmetro é uma referência para o arquivo activity_
main.xml que está na pasta res/layout. É neste arquivo que os
elementos gráficos estão definidos, no caso deste primeiro aplicati-
vo temos apenas um componente do tipo TextView, que será res-
ponsável por mostrar o texto “Hello World!” na tela do dispositivo.
2-9
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 2
IN TR O D U Ç Ã O A O A N D R O ID ST U D I O
vai fazer o download dos arquivos necessários e depois instalar.
Quando este processo terminar, vamos finalmente executar o nos-
so primeiro programa, para isso clique no botão indicado na fi-
gura abaixo:
2-10
EXERCÍCIOS PROPOSTOS
( ) -a) Eclipse
( ) -b) Visual Studio
( ) -c) XCode
( ) -d) Android Studio
( ) -e) Unity
( ) -a) Java
( ) -b) Java Script
( ) -c) C/C++
( ) -d) C#
( ) -e) Kotlin
2-11
( ) -e) O arquivo de Layout nunca deverá ser utilizado no código
sobrescrito do método onCreate.
EX ER C ÍC IO S PR O PO STO S
4) Escolha a afirmativa correta sobre o arquivo activity_main.xml
( ) -a) É neste arquivo que está escrito o código que define o layout
da tela.
( ) -b) É neste arquivo que escrevemos o código em Java que con-
trola o ciclo de vida da MainActivity do aplicativo.
( ) -c) Arquivos .xml não podem ser usados em projetos de aplica-
tivos Android.
( ) -d) Quando damos o mesmo nome que o arquivo MainActivity
não precisamos sobrescrever o método onCreate para ins-
tanciar os elementos do layout.
( ) -e) Quando chamamos o método setContentView, devemos pas-
sar uma String, ou seja, um valor entre aspas duplas indican-
do o caminho absoluto para o arquivo activity_main.xml.
2-12
( ) -d) Não podemos sobrescrever o método onCreate, pois ele não
existe na classe AppCompatActivity.
EX ER C ÍC IO S PR O PO STO S
( ) -e) Não podemos sobrescrever o método onCreate passando
como parâmetro o tipo Bundle?.
7|
override fun onCreate(savedInstanceS-
tate: Bundle?) {
8| super.onCreate(savedInstanceState)
9| setContentView(R.layout.activity_main)
10| }
2-13
( ) -e) Temos que sobrescrever o método onCreate pois ele é cha-
mado assim que o aplicativo é aberto, e é neste momento
EX ER C ÍC IO S PR O PO STO S
que iremos criar os elementos de layout.
2-14
( ) -d) No Android Studio, devemos criar um AVD, e depois clicar
no botão verde de play.
EX ER C ÍC IO S PR O PO STO S
( ) -e) N.d.a
2-15
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
UNIDADE 2:
INTRODUÇÃO A LINGUAGEM KOTLIN
Caro(a) Aluno(a)
Seja bem-vindo(a)!
Ótimos estudos!
Conteúdos da Unidade:
Declaração de variáveis, Tipos de variáveis, Variáveis imu-
táveis e mutáveis, Operadores aritméticos, Operadores de com-
paração, Expressões condicionais com if e else, Expressões
condicionais com when, Estruturas de repetição com while,
Estruturas de repetição com for.
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
CAPÍTULO 3:
VARIÁVEIS, TIPOS E OPERADORES
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
3-3
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
1| fun main() {
2| var quantidade = 3
3| var preco = 2.50
4| var custoTotal = preco * quantidade
5| println(custoTotal)
6| }
3-4
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
3-5
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
1| fun main() {
2| var quantidade = 3
3| println(quantidade::class.simpleName)
4| var preco = 2.50
5| println(preco::class.simpleName)
6| var desconto: Int = 1
7| println(desconto::class.simpleName)
8|
var custoTotal = preco * quantida-
de - desconto
9| println(custoTotal::class.simpleName)
10| println(custoTotal)
11| }
3-6
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
Int
Double
Int
Double
6.5
3-7
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
1| fun main() {
2| val quantidade = 3
3| val preco = 2.50
4| val custoTotal = preco * quantidade
5| println(custoTotal)
6| }
1| fun main() {
2| val quantidade = 3
3| val preco = 2.50
4| val custoTotal = preco * quantidade
5| custoTotal = custoTotal - 1
6| println(custoTotal)
7| }
3-8
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
3-9
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
1| fun main() {
2| val nome = “Roberto”
3| val sobreNome = “Morais”
4| println(“Bem vindo $nome $sobreNome”)
5| }
3-10
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
1| fun main() {
2| val ligado = true
3| val conectado = false
4| println(ligado::class.simpleName)
5| println(ligado)
6| println(conectado)
7| }
3-11
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
Boolean
true
false
1| fun main() {
2|
3-12
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
3-13
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
Soma 7
Subtração 3
Multiplicação 10
Divisão inteira 2
Resto da divisão 1
3-14
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
1| fun main() {
2| var comparacao = 3 == 3
3| println(“3 é igual a 3 ? $comparacao”)
4| comparacao = 3 != 3
3-15
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
3-16
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
3 é igual a 3 ? true
3 é diferente de 3 ? false
3 é maior que 5 ? false
3 é menor que 8 ? true
3 é maior ou igual a 3 ? true
3-17
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
3-18
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
3-19
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 3
3-20
EXERCÍCIOS PROPOSTOS
( ) -a) Quando definimos uma variável com var sabemos que o seu
valor vai mudar, quando definimos uma variável com val sa-
bemos que o seu valor não vai mudar, ou seja estamos defi-
nindo uma variável imutável.
( ) -b) Quando definimos uma variável com val sabemos que o seu
valor vai mudar, quando definimos uma variável com var
sabemos que o seu valor não vai mudar, ou seja, estamos
definindo uma variável imutável.
( ) -c) Não existe diferença entre o uso das duas palavras chaves
val e var.
( ) -d) Quando definimos uma variável com val sabemos que o seu
tipo vai mudar, quando definimos uma variável com var sa-
bemos que o seu tipo não vai mudar, ou seja estamos defi-
nindo uma variável imutável.
( ) -e) N.d.a.
3-21
3) Quando devemos usar o tipo Byte ?
EX ER C ÍC IO S PR O PO STO S
( ) -a) Para armazenar valores monetários que usam apenas duas
casas decimais.
( ) -b) Para armazenar valores inteiros da ordem de grandeza dos
milhares.
( ) -c) Para armazenar valores que representam medidas de com-
primento com até 4 casas decimais.
( ) -d) Para armazenar o número de alunos em uma sala de aula,
suponho que esse número não seja maior que 30.
( ) -e) Para armazenar o número de moléculas em um composto
orgânico.
( ) -a) Para representar uma situação onde podemos ter dois esta-
dos, verdadeiro ou falso.
( ) -b) Armazenar os valores numéricos de 1 até 10.
( ) -c) Quando temos que armazenar o nome de um usuário.
( ) -d) Armazenar os valores da constante Pi com o máximo de ca-
sas decimais.
( ) -e) Armazenar valores monetários para realizar o cálculo do im-
posto devido.
3-22
6) Quando devemos usar uma variável do tipo Boolean?
EX ER C ÍC IO S PR O PO STO S
( ) -a) Quando temos uma situação onde o resultado será apenas
0 ou 1.
( ) -b) Quando queremos armazenar o resultado de uma operação
lógica.
( ) -c) Quando temos uma situação, onde teremos apenas os valo-
res em texto “verdadeiro” ou “falso”.
( ) -d) Quando temos uma situação onde queremos armazenar o
texto que representa as unidades celsius “°C” ou fahrenheit
“°F”
( ) -e) N.d.a
1| fun main() {
2| val x = 9
3| val y = 7
4| val resultado = x % y
5| println(“Resultado $resultado”)
6| }
3-23
8) Considere o código abaixo que utiliza os operadores de comparação e
EX ER C ÍC IO S PR O PO STO S
escolha a alternativa correta.
1| fun main() {
2| val resultado1 = 9 <= 7
3| val resultado2 = 5 >= 5
4| val resultado3 = 7 > 7
5| println(“Resultado1 $resultado1”)
6| println(“Resultado2 $resultado2”)
7| println(“Resultado3 $resultado3”)
8| }
1| fun main() {
2| val x1 = true
3| val x2 = false
4| val x3 = true
5| val x4 = true
6| val resultado1 = (x1 && x2) || (x3 && x4)
7| val resultado2 = x1 || x2 || x3
8| val resultado3 = x1 && x2 && x3 && x4
9| val resultado4 = x1 || x4 || x3 && x2
3-24
10| val resultado5 = (x1 && x2 && x3) ||
(x1 || x4)
EX ER C ÍC IO S PR O PO STO S
11| println(“$resultado1,
12| $resultado2,
13| $resultado3,
14| $resultado4,
15| $resultado5”)
16| }
1| fun main() {
2| val x1 = false
3| val x2 = 10 <= 10
4| val x3 = 1 > 2
5| val x4 = 7 != 7
6| val resultado1 = (x1 && x2) || (x3 && x4)
7| val resultado2 = x1 || x2 || x3
8| val resultado3 = x1 && x2 && x3 && x4
9| val resultado4 = x1 || x4 || x3 && x2
10| val resultado5 = (x1 && x2 && x3) ||
(x1 || x4)
11| println(“$resultado1,
12| $resultado2,
13| $resultado3,
14| $resultado4,
15| $resultado5”)
16| }
3-25
( ) -a) False, true, false, false, false
( ) -b) True, true, false, false, true
EX ER C ÍC IO S PR O PO STO S
( ) -c) False, false, false, false, false
( ) -d) True, true, true, true, true
( ) -e) False, false, true, true, false
3-26
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
CAPÍTULO 4:
CONTROLE DE FLUXO
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 4
C O N TR O LE D E FLU XO
4.1 Introdução
Toda linguagem de programação possui estruturas que con-
trolam o fluxo do programa. As estruturas de repetição são respon-
sáveis por fazer com que um determinado bloco de código se repita
até que uma condição seja ou satisfeita.
Fazem parte deste grupo as estruturas declaradas com as
palavras chaves while e for. É muito comum chamarmos essas
estruturas de laços de repetição.
A outra categoria de estruturas de controle de fluxo são as
expressões condicionais, estas estruturas executam um determi-
nado bloco de código se uma condição for satisfeita, fazem parte
destas estruturas as que são declaradas pelas palavras chaves if,
else e when.
1| if (expressão lógica) {
4-2
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 4
C O N TR O LE D E FLU XO
2|
bloco de código executado quando o re-
sultado da expressão lógica for true
3| } else {
4|
bloco de código executado quando o re-
sultado da expressão lógica for false
5| }
1| fun main() {
2| val media = 3.0
3| if (media >= 5.0) {
4| println(“O aluno foi aprovado na matéria”)
5| } else {
6| println(“O aluno foi reprovado na matéria”)
7| }
8| }
4-3
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 4
C O N TR O LE D E FLU XO
Começamos o programa definindo a variável imutável media
com valor 3.0, esta variável vai armazenar a média na disciplina
que o usuário possui.
Na sequência, na linha 3 utilizamos a palavra-chave if, e
dentro dos parênteses escrevemos a expressão condicional media
>= 5.0, veja que utilizamos o operador de comparação maior ou
igual e como operandos a variável media, e o valor 5.0, ou seja,
sempre que a variável média possuir valor maior que 5.0 está ex-
pressão lógica irá retornar o valor true, caso contrário, se o valor
da variável média for menor que 5.0 então a expressão lógica irá
retornar false.
No caso deste programa, sabemos que o valor da variável
imutável é 3, ou seja 3 é menor que 5, logo o valor da expressão
media >= 5.0, vai ser false e como dito anteriormente, neste
caso o bloco de código dentro das chaves após a palavra else vai
ser executado e a mensagem informando que o usuário foi repro-
vado irá aparecer na tela.
Agora reescreva o código de modo que o valor da variável
media seja 7.5, neste caso a expressão condicional media >=
5.0, retornará o valor true, fazendo com que o bloco de código
das chaves que seguem a expressão condicional seja executado e
portanto neste caso, uma mensagem informando que o usuário foi
aprovado, irá ser exibida na tela.
Faça mais alguns experimentos com esse código, mude o va-
lor para 5.0, e para outros valores até que você se familiarize com
essa estrutura.
Atente para o fato de que a estrutura else é opcional, con-
sidere o programa abaixo que mostra uma mensagem quando o
número armazenado na variável numeroA for maior que o número
armazenado na variável numeroB.
4-4
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 4
C O N TR O LE D E FLU XO
1| fun main() {
2| val numeroA = 30
3| val numeroB = 17
4|
5| if (numeroA > numeroB) {
6|
println(“Número $numeroA é maior
que $numeroB”)
7| }
8| }
4-5
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 4
C O N TR O LE D E FLU XO
1| fun main() {
2| val tipoCafe = 3
3| if (tipoCafe == 1) {
4| println(“Café Latte”)
5| } else if (tipoCafe == 2) {
6| println(“Expresso”)
7| } else if (tipoCafe == 3) {
8| println(“Café Coado”)
9| } else {
10| println(“Opção não encontrada”)
11| }
12| }
4-6
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 4
C O N TR O LE D E FLU XO
Note que a linha 10 não será executada pois o fluxo do pro-
grama saiu do bloco condicional pela linha 10.
Caso o valor da variável tipoCafe, não fosse 1, 2 ou 3 então
apenas nesse caso a linha 10 seria executada.
1| fun main() {
2|
3| val x = 5
4|
5| when (x) {
6| 1 -> println(“X possui o valor 1”)
7| 2 -> println(“X possui o valor 2”)
8| 5 -> println(“X possui o valor 5”)
9| else -> {
10| println(“X possui qualquer outro valor”)
11| }
12| }
13| }
4-7
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 4
C O N TR O LE D E FLU XO
Começamos declarando a variável imutável x com valor igual
a 5, e logo na linha 5 utilizamos a palavra-chave when, para marcar
a estrutura condicional, note que queremos testar qual é o valor da
variável x, neste caso ela foi incluída entre os parênteses logo na
sequência da palavra-chave when.
Após declarada a variável que será testada pela expressão
condicional when abrimos a chave e na linha 6 verificamos se o
valor da variável é igual a 1, caso for o código na frente da marca ->
será executado.
O mesmo é verdade para as linhas 7 e 8, note que o valor da
variável x é 5, portanto o código que será executado está na linha
8, fazendo com que a mensagem informando que x possui o valor
5 será exibida.
Nessa estrutura podemos também utilizar a palavra-cha-
ve else, com o objetivo de desviar o fluxo do programa para o
código entre as chaves do else, caso nenhuma condição acima
seja satisfeita.
Aproveite para mudar o valor da variável x e fazer algumas
experiências com o código do when, por exemplo mudando seu va-
lor para 10 ou mesmo para 2.
4-8
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 4
C O N TR O LE D E FLU XO
1| while (expressão lógica) {
2| bloco de código que será repetido enquanto
a expressão lógica retornar o valor true
3| }
1| fun main() {
2| var x = 1
3| while (x <= 1000) {
4| println(x)
5| x = x + 1
6| }
7| }
4-9
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 4
C O N TR O LE D E FLU XO
fluxo do programa não vai executar o bloco de código definido nas
linhas 4 e 5.
Como inicializamos a variável chamada x com o valor 1, da
primeira vez a expressão lógica x <= 1000, retornará o valor
true, e as linhas 4 e 5 serão executadas, na linha 4 uma mensagem
será mostrada com valor da variável que neste primeiro caso será
1 e na linha 5 incrementamos este valor somando 1, ou seja, após a
execução da linha 5 o valor da variável x mudará para 2.
O valor 2 é menor do que 1000, portanto a expressão lógica
x <= 1000 retornará o valor true, ou seja, novamente as linhas
4 e 5 serão executadas, portanto o valor 2 será mostrado na tela e a
variável x será incrementada em 1, e ao fim da execução da linha 5
esta variável possuirá o valor 3.
Vamos avançar no tempo, e assumir que a variável x chegou
ao valor 1000, neste caso a condição x <= 1000, ainda será válida
e as linhas 4 e 5 serão executadas, portanto o valor 1000 será mos-
trado na tela e na linha 5 o valor da variável x que agora é de 1000,
será incrementado em 1, ou seja, o valor da variável x agora é 1001.
Veja que agora a expressão x <= 1000, é inválida, pois x é
igual a 1001 e 1001 é maior que 1000, portanto esta expressão irá
retornar false e a estrutura de repetição não irá mais executar
as linhas 4 e 5, consequentemente o programa vai terminar e os
números de 1 até 1000 foram mostrados na tela como queríamos.
4-10
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 4
C O N TR O LE D E FLU XO
como utilizar a instrução for para fazer o laço de repetição que re-
solve o problema de mostrar todos os números de 1 até 1000 na tela
1| fun main() {
2| for (x in 1..1000) {
3| println(x)
4| }
5| }
4-11
EXERCÍCIOS PROPOSTOS
1| fun main() {
2| val temperatura = 28
3| if (temperatura > 24) {
4| println(“Baixar Temperatura”)
5| }
6| }
( ) -a) O código acima está errado pois não podemos usar os parên-
teses na linha 3.
( ) -b) O código acima está errado pois a variável temperatura foi
declarada sem um tipo.
( ) -c) O tipo da variável temperatura é Double.
( ) -d) O código está correto e como resultado mostrará a mensa-
gem: Baixar Temperatura.
( ) -e) O comando if, na linha 3 vai gerar um erro, pois este coman-
do não está definido na linguagem Kotlin.
1| fun main() {
2| val opcao = 2
3| if (opcao == 1) {
4| println(“Sabor morango”)
5| } else if (opcao == 2) {
6| println(“Sabor chocolate”)
7| } else if (opcao == 3) {
4-12
8| println(“Sabor limão”)
9| } else {
EX ER C ÍC IO S PR O PO STO S
10| println(“Sabor não encontrado”)
11| }
12| }
4-13
4) Escolha a afirmativa correta sobre as palavras chave if e else na lingua-
EX ER C ÍC IO S PR O PO STO S
gem Kotlin:
1| fun main() {
2| var x = 1
3| while ( x < 20 ) {
4| if (x == 10) {
5| println(“Uma dezena”)
6| } else {
7| println(x)
8| }
9| x = x + 1
10| }
11| }
4-14
( ) -e) O programa vai mostrar na tela os valores de 1 até 19 porém
no valor 10 será mostrada a mensagem: Uma dezena.
EX ER C ÍC IO S PR O PO STO S
6) Considere o código abaixo, e escolha a alternativa correta:
1| fun main() {
2| var x = 1
3| while ( x <= 5 ) {
4| println(x)
5| }
6| }
1| fun main() {
2| var total = 0
4-15
3| for (x in 1..5) {
4| total = total + x
EX ER C ÍC IO S PR O PO STO S
5| }
6| println(total)
7| }
1| fun main() {
2| for (x in 1..10) {
3| if (x % 2 == 0) {
4| println(“$x número é tipo1”)
5| } else {
6| println(“$x número é tipo2”)
4-16
7| }
8| }
EX ER C ÍC IO S PR O PO STO S
9| }
1| fun main() {
2| for (x in 1..20) {
3| var y = 2
4| var tipoNumero = x != 1
5| while (y <= x && tipoNumero) {
6| if ((x != y) && (x % y == 0)) {
7| tipoNumero = false
8| }
9| y = y + 1
10| }
11| println(“$x tipoNumero $tipoNumero”)
12| }
13| }
4-17
( ) -a) O código acima, mostra todos os números pares entre 1 e 20.
( ) -b) O código acima mostra todos os números primos entre 1 e
EX ER C ÍC IO S PR O PO STO S
20.
( ) -c) O código acima mostra todos os números não primos entre
1 e 20.
( ) -d) O código acima mostra a soma de todos os números primos
de 1 até 20.
( ) -e) N.d.a.
1| fun main() {
2| var resultado = 1
3| for (x in 1..10) {
4| if (x % 2 != 0) {
5| resultado = resultado * x
6| }
7| }
8| println(resultado)
9| }
4-18
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
UNIDADE 3:
APROFUNDANDO NA
LINGUAGEM KOTLIN
Caro(a) Aluno(a)
Seja bem-vindo(a)!
Ótimos estudos!
Conteúdos da Unidade:
Dados organizados em lista, listas mutáveis e imutáveis, de-
finição de funções, funções Single-Expression, funções com pa-
râmetros opcionais, Definindo uma classe, Definindo método e
atributos de uma classe, Sobrecarga de métodos, Herança.
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
CAPÍTULO 5:
LISTAS E FUNÇÕES
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 5
LIS TAS E FU N ÇÕ ES
5.1 Introdução
Veremos inicialmente neste capítulo como utilizar listas para
armazenar uma sequência de valores, este conceito será muito útil
mais a frente quando iniciarmos o desenvolvimento do aplicativo.
Na sequência veremos como organizar o código em funções.
5.2 Listas
É muito comum no desenvolvimento de um aplicativo termos
que representar uma lista de elementos, suponha uma lista de com-
pras, onde cada elemento da lista fosse um texto com o nome do
item, não seria nada eficiente, se tivéssemos que criar uma variável
para cada um dos itens desta lista, e imagine só, no caso de uma lista
de compras, poderíamos nem saber o número total de itens.
Considere o código abaixo, onde vamos definir uma lista,
onde cada elemento foi incluído na definição da lista.
1| fun main() {
2|
val listaCompra =
listOf(“Tomate”,”Batata”,”Açucar”)
3| println(listaCompra[0])
4| }
5-3
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 5
LIS TAS E FU N ÇÕ ES
Note que para acessar um determinado item de uma posi-
ção usamos o nome da variável seguido do índice entre colchetes
como no caso do código onde acessamos o item 0 escrevendo o
código listaCompra[0].
Caso fosse necessário acessar o valor na segunda posição, usamos
o código listaCompra[2] e com isso acessaremos a palavra Açúcar.
É importante deixarmos claro que a variável listaCompra
não poderá ter seus itens modificados, ou mais itens adicionados ou
até itens removidos, para criarmos uma lista que pode ser modifica-
da, vamos utilizar a função mutableListOf, veja no código abaixo
que agora podemos alterar um item já existente, remover um item
numa determinada posição ou adicionar um item em outra posição.
O código abaixo onde criaremos a variável listaCompra
utilizando a função mutableListOf.
1| fun main() {
val listaCompra = mutableListOf(“Toma-
2|
te”,”Batata”,”Açucar”)
3| listaCompra[0] = “Laranja”
4| listaCompra.add(“Abacate”)
5| listaCompra.removeAt(2)
6| for (item in listaCompra) {
7| println(item)
8| }
9| }
5-4
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 5
LIS TAS E FU N ÇÕ ES
Já na linha 2 criamos a variável listaCompra, mas note
que agora utilizamos a função mutableListOf, pois desta vez,
poderemos fazer modificações nesta variável.
Modificamos o item da posição 0 para o texto “Laranja”, em
seguida adicionamos mais um item, identificado pelo texto “Aba-
cate”, note que na linha 4 utilizamos a função add, da lista e pas-
samos como parâmetro o texto “Abacate”, desta maneira este item
será adicionado ao final da lista.
Agora, na linha 5, utilizamos a função removeAt, para re-
mover o item da posição 2, ou seja, removemos a palavra “Açúcar”
da lista. Por fim utilizamos a estrutura de repetição com a instru-
ção for, para percorrer e mostrar todos os elementos da lista na
tela. A saída deste programa será:
Laranja
Batata
Abacate
5.3 Funções
Imagine que precisamos mostrar no programa uma mensa-
gem de erro em vários pontos do código, poderíamos escrever essa
mesma mensagem em vários lugares, mas imagine se por acaso,
tivéssemos que mudar a mensagem, então teríamos que modificar
todos esses pontos do código.
Por meio das funções podemos escrever este código uma
única vez, dentro de uma função e chamar essa função em vários
pontos do nosso código. Caso fosse necessário mudarmos esta
5-5
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 5
LIS TAS E FU N ÇÕ ES
mensagem, teríamos apenas que modificar o código de dentro
da função.
Outra utilidade muito importante das funções é que por meio
delas melhoramos a organização do código, isolando partes do código
responsáveis por uma tarefa dentro de uma mesma função. Logo abai-
xo, escrevemos de maneira genérica como é a estrutura de uma função:
5-6
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 5
LIS TAS E FU N ÇÕ ES
Cada parâmetro de uma função deverá ter o seu tipo decla-
rado, isso é feito pelo uso do símbolo dois-pontos, colocado logo
após o nome do parâmetro. Após o símbolo dois-pontos devemos
escrever o tipo do parâmetro.
Por fim, fechamos o parêntese e usamos novamente o símbo-
lo dois-pontos, só que agora iremos definir qual o tipo do retorno
da função, portanto logo depois deste símbolo devemos escrever
o tipo de retorno, lembre-se que uma função não precisa retornar
nenhum valor, ou seja esta parte pode ser omitida.
Nesta mesma linha terminamos a declaração da função uti-
lizando o símbolo abre chave {. Até agora o que escrevemos pode
ser considerado a assinatura da função. O código que a função exe-
cuta virá na próxima linha, este será o código que vai ser executado
quando a função for chamada.
Por fim, caso a função retorne um valor, devemos escrever a
palavra chave return, colocando um espaço em branco e escre-
vendo um valor literal ou o nome de uma variável, que sejam do
mesmo tipo do retorno declarado na assinatura da função.
Terminamos então a definição de função, usando o símbolo
da chave }.
Logo abaixo, escrevemos uma função, que apenas irá mos-
trar uma mensagem genérica simulando que um erro aconteceu.
1| fun mostraMensagemDeErro() {
2|
println(“Um erro aconteceu tente
mais tarde !”)
3| }
4|
5-7
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 5
LIS TAS E FU N ÇÕ ES
5| fun main() {
6| mostraMensagemDeErro()
7| }
5-8
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 5
LIS TAS E FU N ÇÕ ES
vamos considerar que os valores da base e do lado do retângulo
podem ter casas decimais, vamos utilizar o tipo Double para estes
dois parâmetros.
Esta função também terá um valor de retorno que será a área
do retângulo, este valor também será do tipo Double. Veja abaixo
como ficou o código desta função:
1| fun calculaAreaRetangulo(base:Double,
altura:Double):Double {
2| return base * altura
3| }
4|
5| fun main() {
6| val area = calculaAreaRetangulo(5.5, 3.7)
7| println(“A área do retângulo é $area”)
8| }
5-9
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 5
LIS TAS E FU N ÇÕ ES
Note que colocamos os parâmetros entre parênteses, na se-
quência utilizamos o símbolo dois pontos, para indicarmos que a
função irá retornar um valor do tipo Double.
Vamos então começar o código da função, para indicar isso,
devemos usar o símbolo abre chaves {. Na linha 2 escrevemos o
código que será usado para calcular a área do retângulo, ou seja
multiplicamos os parâmetros base e altura, e nesta mesma li-
nha retornamos o valor da multiplicação.
Por fim, terminamos a definição completa da função com o
símbolo fecha chaves }. Como dito anteriormente, ao executarmos
o programa, o compilador procura a função main como ponto de
execução inicial, neste caso definimos a função main na linha 5,
e logo na linha 6 chamamos a função calculaAreaRetangu-
lo, passando como parâmetros os valores 5.5 para base e 3.7 para
altura, note que armazenamos o resultado da função na variável
imutável chamada área, e por fim mostramos este valor na saída
do programa.
A linguagem Kotlin fornece um recurso para simplificarmos
a declaração de funções como essa que podem ser escritas com
apenas uma linha, chamamos este recurso de Single-Expres-
sion functions, vamos reescrever a função calculaAreaRe-
tangulo, utilizando este recurso:
5-10
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 5
LIS TAS E FU N ÇÕ ES
O nome dos parâmetros foi modificado apenas para a decla-
ração da função caber em uma linha no formato deste material.
Podemos também definir uma função com parâmetros op-
cionais veja no código abaixo como essa função pode ser escrita:
1| fun main() {
2| calculaAreaQuadrado(3.0)
3| calculaAreaQuadrado(2.0,”cm²”)
4| }
5-11
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 5
LIS TAS E FU N ÇÕ ES
Perceba que na linha 2, fizemos uma chamada para a função
calculaAreaQuadrado, passando como parâmetro apenas o va-
lor do lado do quadrado omitindo o parâmetro do tipo String que
representa a unidade de área.
Na sequência, fizemos uma chamada para a função calcu-
laAreaQuadrado, porém, agora passamos o segundo parâmetro
que representa a unidade da área do quadrado como sendo cm²,
neste caso, esta String fará parte da mensagem gerada pela fun-
ção e substituirá a String padrão.
Veja abaixo que a saída do programa mostra na linha 1 que a
área do quadrado é 9 mm², pois na primeira chamada omitimos o
parâmetro e neste caso o valor padrão foi usado. Na linha 2, porém
a mensagem mostrada na tela, aparece com a unidade cm²
5-12
EXERCÍCIOS PROPOSTOS
1| fun main() {
2| val listaDeItens = listOf(“Barraca”,
3| “Fogareiro”,
4| “Faca”,
5| “Garfo”)
6| println(listaDeItens.count())
7| println(listaDeItens[0])
8| println(listaDeItens[3])
9| }
5-13
2) Considere o código abaixo e escolha a afirmativa correta:
EX ER C ÍC IO S PR O PO STO S
1| fun main() {
2| val listaDeItens = listOf(“Barraca”,
3| “Fogareiro”,
4| “Faca”,
5| “Garfo”)
6|
7| listaDeItens[0] = “Lanterna”
8| listaDeItens.add(“Cobertor”)
9| }
( ) -a) O Código acima não vai funcionar, pois a lista criada pela
instrução listOf não pode ser modificada.
( ) -b) O Código vai falhar pois a indexação da lista começa sempre
no índice 1 e nunca no 0.
( ) -c) Como a lista foi criada com listOf a linha 7 vai executar com
sucesso, porém a linha 8 vai falhar pois não podemos adicio-
nar um novo elemento.
( ) -d) Como a lista foi criada com listOf a linha 7 vai falhar, porém,
a linha 8 vai executar com sucesso pois podemos adicionar
um novo elemento.
( ) -e) Basta mudar a palavra chave de val para var e o resto do có-
digo vai ser executado com sucesso.
5-14
17| listaDeItens.removeAt(1)
18| println(listaDeItens.count())
EX ER C ÍC IO S PR O PO STO S
19| for (item in listaDeItens) {
20| println(item)
21| }
22| }
( ) -a) O código acima não vai compilar pois na linha 2 foi utiliza-
da a palavra chave val, o que tornará a variável listaDeItens
imutável, e portanto ela não poderá ser alterada nas linhas
abaixo.
( ) -b) Teremos um erro na compilação gerado pela linha 6 pois o
índice 0 não existe na lista, sempre devemos começar pelo
índice 1.
( ) -c) O código executa e a resposta será:
4
Lanterna
Faca
Garfo
Cobertor
( ) -d) O código executa e a resposta será
3
Barraca
Faca
Cobertor
( ) -e) Existe um erro na linha 10, pois não foi utilizado um índice
na declaração do laço de repetição for.
1| fun main() {
2| val notas = listOf(5.3,
3| 7.1,
4| 8.2,
5| 6.6)
5-15
6|
7| var variavel1 = 0.0
EX ER C ÍC IO S PR O PO STO S
8| for (nota in notas) {
9| variavel1 = variavel1 + nota
10| }
11| val variavel2 = variavel1 / notas.count()
12| println(variavel2)
13| }
( ) -a) Uma função na linguagem Kotlin sempre deve ter o seu tipo
de retorno declarado, mesmo quando essa função não retor-
nar nenhum valor.
( ) -b) É obrigatório na linguagem Kotlin, que uma função receba
pelo menos um parâmetro.
( ) -c) Na linguagem Kotlin, podemos declarar uma função apenas
utilizando a palavra-chave fun, sem passar nenhum parâme-
tro e sem definir o seu tipo de retorno.
( ) -d) Na linguagem Kotlin, não é necessário o uso de chaves para
marcar o bloco de código de uma função de mais de uma
linha.
( ) -e) N.d.a.
5-16
6) Considere o código abaixo e escolha a afirmativa correta:
EX ER C ÍC IO S PR O PO STO S
1| fun calculaAreaCirculo(r:Double) = PI
* r.pow(2)
5-17
( ) -c) Podemos usar a palavra-chave return para retornar um va-
lor ao final da função mesmo que essa função não possua um
EX ER C ÍC IO S PR O PO STO S
tipo definido.
( ) -d) A palavra-chave return pode vir por fora das chaves que de-
finem o bloco de código da função.
( ) -e) N.d.a.
5-18
10) Considere o código abaixo e escolha a afirmativa correta:
EX ER C ÍC IO S PR O PO STO S
1| fun retornaNumeros(listaDeNumeros: Lis-
t<Int>): List<Int> {
2| val resultado = mutableListOf<Int>()
3| for (numero in listaDeNumeros) {
4| if (numero % 2 == 0) {
5| resultado.add(numero)
6| }
7| }
8| return resultado
9| }
5-19
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
CAPÍTULO 6:
CLASSES
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
6.1 Introdução
Veremos neste capítulo uma breve introdução ao conceito
de classe que é fundamental da programação orientada a obje-
tos e que será necessário para o desenvolvimento dos aplicativos
deste material.
A programação orientada a objetos modela os elementos uti-
lizados no mundo real em classes, as classes funcionam como mol-
des que serão utilizados na construção de objetos.
O conceito de classe é muito importante quando vamos de-
senvolver aplicativos para a plataforma Android, pois para utilizar-
mos corretamente a biblioteca de maneira confortável precisamos
saber o básico sobre este conceito.
6-2
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
6| var nome = “Quadrilatero”
7| val l1 = l1
8| val l2 = l2
9| val l3 = l3
10| val l4 = l4
11| }
6-3
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
Agora que temos a classe Quadrilatero definida, vamos
ver como podemos instanciar um objeto dessa classe e utilizar os
seus atributos.
1| fun main() {
2|
val quadrilatero =
Quadrilatero(3.0,7.0,5.0,8.0)
3| quadrilatero.nome = “Meu Quadrilatero”
4|
println(“O nome do quadrilatero é:
${quadrilatero.nome}”)
5|
println(“O valor de um dos lados é:
${quadrilatero.l1}”)
6| }
6-4
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
6.3 Definindo métodos em uma Classe
Além de atributos, uma classe também pode conter funções,
que por estarem em uma classe chamaremos de método por con-
venção. Vamos tomar como exemplo, o caso de queremos escre-
ver um método que calcula o perímetro do quadrilátero, da mate-
mática elementar sabemos que o perímetro é dado pela soma dos
comprimentos dos lados do quadrilátero. Veja no código abaixo a
implementação deste método:
6-5
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
A definição da classe é a mesma que fizemos anteriormente,
porém agora na linha 12 definimos o método calculaPerime-
tro, veja que este método não recebe nenhum parâmetro, e retor-
na como valor um valor do tipo Double, que será a soma de todos
os lados, ou seja será dado pela soma dos atributos l1, l2, l3 e
l4. Veja que utilizamos a palavra return para retornar o valor
desta soma.
Pronto a classe Quadrilatero, agora possui um método
que calcula o perímetro, mas como vamos utilizar este novo méto-
do? Para isso devemos fazer como no código abaixo:
1| fun main() {
2|
val quadrilatero =
Quadrilatero(3.0,7.0,5.0,8.0)
3|
val perimetro = quadrila-
tero.calculaPerimetro()
4| println(perimetro)
5| }
6-6
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
No capítulo anterior, mostramos que as funções podem ter
parâmetros opcionais, declaramos isto quando, na definição do pa-
râmetro atribuímos a ele um valor.
Podemos utilizar este mesmo recurso, quando definimos os
parâmetros necessários ao construtor de uma classe. Definimos o
construtor da classe Quadrilatero com 4 parâmetros obrigató-
rios, mas pense no caso onde queremos construir uma instância
da classe Quadrilatero, que irá representar um retângulo, neste
caso, como o retângulo possui dois pares de lados iguais, seriam
necessário apenas dois parâmetros.
Vamos então, no código abaixo, reescrever o construtor da
classe Quadrilatero, seguindo essas ideias.
6-7
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
14| }
15| }
1| fun main() {
2| val quadrilatero = Quadrilatero(10.0, 3.0)
3|
val perimetro = quadrila-
tero.calculaPerimetro()
4|
5| println(“Lado1 ${quadrilatero.l1}”)
6| println(“Lado2 ${quadrilatero.l2}”)
7| println(“Lado3 ${quadrilatero.l3}”)
8| println(“Lado4 ${quadrilatero.l4}”)
9|
10| println(“Perimetro $perimetro”)
11| }
6-8
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
linhas de 5 até 8 mostramos os valores de cada um dos lados, note
que para os lados l3 e l4 deveremos ter respectivamente os valo-
res 10.0 e 3.0, veremos que isso acontece na saída deste programa,
por fim apenas mostramos na tela o valor do cálculo do perímetro
para provarmos que, com a alteração do construtor o perímetro
continua sendo calculado corretamente. Veja abaixo como ficou a
saída do programa:
Lado1 10.0
Lado2 3.0
Lado3 10.0
Lado4 3.0
Perimetro 26.0
6-9
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
palavra override, que diz ao compilador que iremos sobrescre-
ver este método com uma nova implementação.
Veja abaixo como vai ficar o código da classe Quadrilate-
ro com o método toString sobrescrito:
6-10
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
20| $l1, $l2, $l3, $l4 .”””
21| }
22| }
6-11
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
Se não utilizássemos a sequência de três aspas duplas, te-
ríamos que concatenar todos os valores, o que deixaria o código
difícil de ler.
Por fim fechamos, utilizamos o símbolo fecha chaves } e fi-
nalizamos o método. Pronto, agora toda a vez que for necessário
mostrar informações sobre a classe Quadrilatero, basta apenas
instânciarmos o objeto e passar a sua referência para a função
println, isso foi feito no código abaixo:
1| fun main() {
2| val quadrilatero = Quadrilatero(10.0, 3.0)
3| quadrilatero.nome = “Retângulo”
4| println(quadrilatero)
5| }
6-12
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
Veja que o texto da saída é exatamente o texto que foi es-
crito no corpo do método toString que foi sobrecarregado na
classe Quadrilátero.
6-13
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
3| l3: Double = l1,
4| l4: Double = l2) {
5| :
6| :
7| }
6-14
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
20| }
21| }
6-15
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 6
CLASSES
Com isso temos a classe Retângulo, pronta para ser utiliza-
da, veja no código abaixo como fazer uso desta nova implementação:
1| fun main() {
2| val retangulo = Retangulo(3.0, 7.0)
3| val area = retangulo.calculaArea()
4| println(“Área do ${retangulo.nome} é $area”)
5| perimetro = retangulo.calculaPerimetro()
6| println(“Perimetro do ${retangulo.nome}
é $perimetro”)
7| }
6-16
EXERCÍCIOS PROPOSTOS
6-17
( ) -b) O código acima declara uma classe chamada Heroi, com os
atributos nome, pontosDeVida e pontosDeAtaque. O atribu-
EX ER C ÍC IO S PR O PO STO S
to nome poderá ser modificado posteriormente.
( ) -c) Podemos construir objetos do tipo Herói, sem passar nenhum
parâmetro para o construtor, pois os parâmetros são opcionais.
( ) -d) Depois que instanciamos um objeto do tipo Herói, não podere-
mos modificar os atributos pontosDeVida nem pontosDeAtaque.
( ) -e) N.d.a
6-18
( ) -a) O método descrito na linha 7 vai gerar um erro pois o atribu-
to pontosDeVida não pode ser modificado.
EX ER C ÍC IO S PR O PO STO S
( ) -b) A saída deste programa será: Pontos de vida 40.0, Herói so-
freu dano, pontos de vida restantes 30.0, O Herói morreu.
( ) -c) A saída deste programa será: Pontos de vida 40.0, Herói so-
freu dano, pontos de vida restantes 30.0.
( ) -d) O programa irá gerar um erro pois o método sofreDano não
foi marcado como public.
( ) -e) A variável pontosRestantes terá o valor 0 após a execução
da linha 19.
6-19
( ) -a) Existe um erro na linha 9 pois a palavra-chave override, não
existe na linguagem Kotlin.
EX ER C ÍC IO S PR O PO STO S
( ) -b) Ao executar o programa a mensagem mostrada na tela será
algo similar a: Heroi@5a07e868, que é o endereço de me-
mória do objeto herói.
( ) -c) A saída do programa na tela será:
Dados do herói:
Nome.......: Cron
PtsVida....: 17.0
PtsAtaque..: 23.0
( ) -d) A sobrecarga do método toString está errada na classe Herói
pois este método recebe uma String como parâmetro.
( ) -e) Na linha 19 devemos passar como parâmetro a classe Herói
e não uma instância dela.
6-20
6| if (pontosDeVida <= 0) {
7| println(“O Herói morreu.”)
EX ER C ÍC IO S PR O PO STO S
8| }
9| return pontosDeVida
10| }
11| }
12|
13| class HeroiMagico(nome: String,
14| pontosDeVida: Double,
15| pontosDeAtaque: Double,
16| pontosDeMagia: Double = 30.0) :
17| Heroi(nome,
18| pontosDeVida,
19| pontosDeAtaque) {
20|
21| var pontosDeMagia = pontosDeMagia
22| fun usaMagia(consumoDeMagia: Double) {
23| pontosDeMagia = pontosDeMa-
gia - consumoDeMagia
24| if (pontosDeMagia > 0 ) {
25| println(“Feitiço lançado.”)
26| } else {
27| println(“Sem magia.”)
28| }
29| }
30| }
31|
32| fun main() {
33| var heroiMagico = HeroiMagico(“Cron”,
17.0, 23.0)
34| heroiMagico.usaMagia(10.0)
35| heroiMagico.usaMagia(40.0)
36| heroiMagico.sofreDano(30.0)
37| }
6-21
( ) -a) Durante a execução do programa um erro vai acontecer pois
o método usaMagia depende do atributo pontosDeMagia
EX ER C ÍC IO S PR O PO STO S
que não possui valor nenhum pois não foi passado como pa-
râmetro no construtor da classe.
( ) -b) A função usaMagia, não poderá ser usada pois não foi mar-
cada como public.
( ) -c) A classe HeroiMagico deverá ser ter o modificador open,
para que ela possa herdar corretamente os atributos e mé-
todos da classe Herói.
( ) -d) O código vai gerar um erro de compilação pois o atributo
pontosDeMagia não é opcional.
( ) -e) O programa executa sem erros e a saída dele será:
Feitiço lançado.
Sem magia.
O Herói morreu.
6-22
( ) -a) O código acima não vai compilar pois existe apenas um erro
na linha 9.
EX ER C ÍC IO S PR O PO STO S
( ) -b) O código acima não vai compilar, pois na linha 9 é necessá-
rio declarar que o método retorna o tipo Double. E na linha
1 precisamos remover a palavra chave open
( ) -c) Existe apenas um erro neste código.
( ) -d) Na linha 11 é necessário declarar a expressão condicional en-
tre parênteses.
( ) -e) Para que o código compile, precisamos adicionar o tipo de
retorno do método na linha 9 e na linha 11, é necessário co-
locarmos a expressão condicional entre parênteses.
6-23
37|
38| }
EX ER C ÍC IO S PR O PO STO S
39| }
( ) -a) O código acima não compila, pois está faltando apenas a pa-
lavra-chave override, na declaração do método toString.
( ) -b) O código acima não compila, pois na linha 16 o método so-
freDano foi definido como retornando o tipo Double, porém
neste método, não foi definido nenhum valor de retorno.
( ) -c) Para que o código compile, falta apenas colocar na linha 13
três aspas duplas.
( ) -d) Para que este código compile, precisamos adicionar na linha
13, três aspas duplas, na linha 9 devemos marcar o método
toString com a palavra-chave override e por fim colocar a
palavra-chave return e na sequência um valor de retorno no
método sofreDano.
( ) -e) N,d,a.
6-24
16| open fun sofreDano(pontosDeDano: Doub-
le): Double {
EX ER C ÍC IO S PR O PO STO S
17| pontosDeVida = pontosDeVida - pontosDeDano
18| if (pontosDeVida <= 0) {
19| println(“O Herói morreu.”)
20| }
21| return pontosDeVida
22| }
23| }
24|
25| class HeroiMagico(nome: String,
26| pontosDeVida: Double,
27| pontosDeAtaque: Double,
28| pontosDeMagia: Double = 30.0) :
29| Heroi(nome,
30| pontosDeVida,
31| pontosDeAtaque) {
32|
33| var pontosDeMagia = pontosDeMagia
34| fun usaMagia(consumoDeMagia: Double) {
35| pontosDeMagia = pontosDeMa-
gia - consumoDeMagia
36| if (pontosDeMagia > 0 ) {
37| println(“Feitiço lançado.”)
38| } else {
39| println(“Sem magia.”)
40| }
41| }
42|
43| override fun sofreDano(pontosDeDano:
Double): Double {
44| super.sofreDano(pontosDeDano)
45| pontosDeMagia = pontosDeMagia + pon-
tosDeDano * 0.1
46| return pontosDeVida
6-25
47| }
48| }
EX ER C ÍC IO S PR O PO STO S
49|
50| fun main() {
51| var heroiMagico = HeroiMagico(“Cron”,
57.0, 23.0)
52| println(“Pontos de magia ${heroiMa-
gico.pontosDeMagia}”)
53| heroiMagico.sofreDano(30.0)
54| println(“Pontos de magia ${heroiMa-
gico.pontosDeMagia}”)
55| }
6-26
10| ptsVida....: $pontosDeVida
11| ptsAtaque..: $pontosDeAtaque “””
EX ER C ÍC IO S PR O PO STO S
12| }
13| }
14|
15| class HeroiMagico(nome: String,
16| pontosDeVida: Double,
17| pontosDeAtaque: Double,
18| pontosDeMagia: Double = 30.0) :
19| Heroi(nome,
20| pontosDeVida,
21| pontosDeAtaque) {
22| var pontosDeMagia = pontosDeMagia
23| override fun toString(): String {
24| var dadosHeroi = super.toString()
25| dadosHeroi = dadosHeroi + “\n ptsMa-
gia...: $pontosDeMagia”
26| dadosHeroi = dadosHeroi + “\n Classe:
Herói Mágico”
27| return dadosHeroi
28| }
29| }
30|
31| fun main() {
32| var heroiMagico = HeroiMagico(
33| “Cron”,
34| 57.0,
35| 43.0,
36| pontosDeMagia = 70.0)
37| println(heroiMagico)
38| }
6-27
Dados do herói:
Nome.......: Cron
EX ER C ÍC IO S PR O PO STO S
PtsVida....: 57.0
PtsAtaque..: 43.0
( ) -c) A saída do programa será:
Dados do herói:
Nome.......: Cron
PtsVida....: 57.0
PtsAtaque..: 43.0
PtsMagia...: 30.0
Classe: Herói Mágico
( ) -d) O programa não compila, pois o parâmetro pontosDeMagia
não pode ser diferente de 30.
( ) -e) A saída do programa será:
Dados do herói:
nome.......: Cron
ptsVida....: 57.0
ptsAtaque..: 43.0
ptsMagia...: 70.0
Classe: Herói Mágico
6-28
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
UNIDADE 4:
PRIMEIRO APLICATIVO:
ÁLCOOL OU GASOLINA
Caro(a) Aluno(a)
Seja bem-vindo(a)!
Ótimos estudos!
Conteúdos da Unidade:
Definição e criação de layouts, O arquivo activity_main.
xml, o Editor de layout do Android Studio, Definição de Cons-
traintLayout, TextView, EditText, Definindo a MainActivity, O
método onCreate, Definição de Enum.
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
CAPÍTULO 7:
DEFININDO O LAYOUT
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 7
D EFIN IN D O O LAYO UT
7.1 Introdução
Agora que já temos alguma base na linguagem Kotlin, pode-
mos começar a desenvolver o primeiro aplicativo para a plataforma
Android. No Brasil, os carros bi-combustíveis são a maioria, mas
quando vamos abastecer, fazemos aquela conta básica dividindo o
preço do litro do álcool pelo preço do litro da gasolina.
Se o valor desta divisão for menor que 0.7 então dizemos que
o álcool é mais indicado, caso contrário, se o valor desta divisão for
maior ou igual a 0.7 então dizemos que a gasolina é mais indicada.
Veja que para fazermos este cálculo, precisaremos de forne-
cer ao aplicativo os valores dos combustíveis, ou seja, precisamos
de dois campos que aceitem esses valores.
Precisaremos também de um lugar na tela para mostrar o
resultado, ou seja, um lugar para mostrarmos uma frase informan-
do qual combustível é mais indicado em termos econômicos para
ser comprado.
7-3
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 7
D EFIN IN D O O LAYO UT
Não se esqueça de marcar a linguagem como Kotlin, e pode
deixar como padrão o Minimum SDK. Após entrar com as informa-
ções descritas acima, clique no botão Finish.
Neste instante o Android Studio, mudará para a tela de pro-
jeto e poderemos começar a desenvolver o nosso aplicativo.
7-4
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 7
D EFIN IN D O O LAYO UT
possui o texto “Hello World!”, para isso escolha este elemento no
editor e aperte a tecla delete.
Com este elemento removido vamos começar adicionando
um elemento do tipo TextView, este elemento é responsável por
mostrar um texto na tela do dispositivo, vamos usar este Text-
View para mostrar o texto “Preço do Álcool”.
Para isso arraste o elemento TextView para a tela de
layout, note que o elemento raiz do layout por padrão é do
tipo ConstraintLayout.
Esse componente é invisível e provê ao layout um sistema de
restrições para o posicionamento dos elementos na tela, no caso
do elemento TextView que adicionamos vamos, colocar uma res-
trição que centraliza este componente horizontalmente na tela,
para isso clique com o botão direito, escolha a opção Center, e
escolha na sequência o item Horizontally, como mostrado na
figura abaixo:
7-5
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 7
D EFIN IN D O O LAYO UT
Figura 7-2: Adicionando restrições.
7-6
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 7
D EFIN IN D O O LAYO UT
Figura 7-3: Adicionando restrições verticais.
7-7
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 7
D EFIN IN D O O LAYO UT
Como feito anteriormente adicione uma restrição de cen-
tralização horizontal e outra restrição vertical da mesma maneira
como foi feito com o componente TextView.
Vamos modificar mais algumas propriedades do Edit-
TextNumberDecimal, para melhorar o layout, vamos centralizar
o texto do campo, para isso selecione este componente e no lado
direito, no grupo All Attributes, expanda a opção gravity, e
marque a opção center_horizontal.
Por fim, vamos modificar o atributo id, este atributo é o
identificador do elemento EditTextNumberDecimal, e será
utilizado no momento em que for necessário pegarmos o valor do
campo para efetuarmos a regra de negócio. Este campo aparece
no grupo Attributes, logo no topo, modifique seu conteúdo
para campoValorAlcool.
Ao final desta etapa o layout deve estar parecido com o da fi-
gura abaixo, mas sinta-se à vontade para experimentar as diversas
opções, mude a fonte do texto,o tamanho a cor, quanto mais experi-
mentos você fizer, mais familiarizado você ficará com a ferramenta.
7-8
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 7
D EFIN IN D O O LAYO UT
arrastar mais um elemento do tipo TextView, mudar o atributo
text para Gasolina e o atributo textSize para 20sp.
Feito isso, vamos colocar as restrições de Layout, vamos
inicialmente colocar a restrição de centralização horizontal e a res-
trição de margem superior.
Por fim, temos que adicionar mais um elemento do tipo
EditTextNumberDecimal, que será onde o usuário vai entrar o
valor do preço da gasolina.
Devemos mudar o campo id para que possamos poste-
riormente, pegar o valor deste campo. Vamos então colocar o va-
lor campoValorGasolina.
Da mesma maneira como feito anteriormente, vamos marcar
no atributo gravity a opção center_horizontal. Ao final des-
tes dois passos teremos o seguinte resultado:
7-9
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 7
D EFIN IN D O O LAYO UT
botão, que quando for pressionado, irá fazer o cálculo da divisão
do preço do álcool pelo preço da gasolina.
Para adicionar este botão, selecione no grupo Palette no
lado esquerdo da tela do Android Studio, a opção Buttons, depois
na lista da direita escolha a opção Button, e arraste para o editor
de layouts.
Inicialmente vamos mudar o título do botão, para isso se-
lecione o elemento na tela de layout e no canto direito da tela do
Android Studio escolha a opção text, mude o texto deste campo
para CALCULAR. Para o botão também precisaremos mudar o texto
do id, neste caso, modifique o valor para botaoCalcular.
Agora vamos adicionar as restrições de layout, uma restrição
para centralizar o botão horizontalmente e outra para termos uma
margem superior do campo texto que será utilizado para a entrada
do preço da gasolina.
O último elemento que vamos adicionar ao layout do nosso
aplicativo será novamente do tipo TextView, para isso selecione
no grupo Palette, a opção Common, e na lista adjacente, arras-
te o item TextView para o editor de layout, logo abaixo do bo-
tão calcular.
Edite o atributo text deste componente para o valor: Com-
bustível mais vantajoso. Modifique também o atributo
textSize para 20sp.
Como utilizaremos este componente para exibir qual com-
bustível vale mais apenas, precisaremos mudar o valor do cam-
po id, para um valor mais amigável. Modifique então o valor
para textCombustivel.
7-10
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 7
D EFIN IN D O O LAYO UT
Chegou a vez de adicionarmos as restrições de layout para
este componente, vamos novamente adicionar uma restrição de
centralização horizontal e outra para a margem superior.
Por fim o layout do nosso aplicativo que mostra qual com-
bustível é mais vantajoso deverá ficar assim:
7-11
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 7
D EFIN IN D O O LAYO UT
escrever o código na linguagem Kotlin, no arquivo MainActivi-
ty, veremos isso no próximo capítulo.
7-12
EXERCÍCIOS PROPOSTOS
( ) -a) App/java/res
( ) -b) Java/app/res
( ) -c) App/res/layout
( ) -d) App/res/drawable
( ) -e) App/res/values
7-13
4) Para que serve um elemento de layout do tipo EditText ?
EX ER C ÍC IO S PR O PO STO S
( ) -a) Este elemento não existe na plataforma Android.
( ) -b) Para criar um elemento que vai representar um campo texto
na tela.
( ) -c) Para criar um elemento que vai representar um botão na tela.
( ) -d) Este elemento cria um espaço na tela para que uma imagem
seja exibida.
( ) -e) N.d.a.
7-14
( ) -e) Na tela de desenho de layout devemos clicar com o botão di-
reito no elemento que vai ser centralizado e escolher a opção
EX ER C ÍC IO S PR O PO STO S
Refactor.
7-15
( ) -c) É o texto que está armazenado no atributo text que será exi-
bido na tela onde o elemento TextView foi definido.
EX ER C ÍC IO S PR O PO STO S
( ) -d) O atributo text do elemento TextView deve ter o mesmo
valor do atributo id, senão um erro vai acontecer durante a
compilação.
( ) -e) Não podemos modificar o atributo text do elemento Text-
View por meio do código Kotlin.
10) Como criamos um novo projeto Android com uma Empty Activity utilizan-
do o Android Studio?
7-16
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
CAPÍTULO 8:
CODIFICANDO A ACTIVITY
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
8.1 Introdução
É no arquivo MainActivity que deveremos escrever a lógi-
ca do nosso aplicativo, veja que é neste arquivo que a classe Mai-
nActivity foi definida.
Nos capítulos anteriores explicamos como o mecanismo de
herança funciona na programação orientada a objetos, este concei-
to é utilizado aqui, pois a classe MainActivity, herda as proprie-
dades da classe AppCompatActivity.
Note que o método onCreate está marcado pelo modifica-
dor override, ou seja, o código que escrevemos neste método
será executado assim que o aplicativo for iniciado.
8-2
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
Na linha 9 mostramos a definição da classe MainActivity,
e logo na linha 11 definimos a variável campoPrecoGasolina,
definimos esta variável mutável como sendo do tipo EditText e
marcamos a sua definição com a palavra-chave lateinit. Na se-
quência fazemos o mesmo criando a variável campoPrecoAlco-
ol, que também é do tipo EditText.
O modificador lateinit diz ao compilador que esta vari-
ável será inicializada mais a frente, e isso vai acontecer no novo
método que iremos criar chamado defineCampos, como mostrado
logo abaixo.
8-3
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
o Android, transforma o atributo do tipo texto chamado id, que
utilizamos no editor de layout para colocar o nome do elemento
em uma constante que é acessada por meio da classe R.
Outro ponto importante é que passamos o tipo do elemento
que estamos procurando entre os símbolos < e >, neste caso como
procuramos um elemento do tipo EditText escrevemos <Edit-
Text>, por meio desta notação é possível passar para um método
um tipo qualquer como parâmetro, esta propriedade faz parte do
conceito de Generics, que não será escopo deste material.
Por fim teremos uma referência do elemento ao elemento
gráfico que possui o valor do preço do combustível do tipo gasoli-
na, fizemos tudo isso pois precisamos deste valor no cálculo, que
será feito para dizer qual combustível é mais vantajoso.
Na linha 23 fizemos a mesma coisa para o elemento gráfico
que armazena o valor do preço do álcool, utilizamos da mesma ma-
neira o método findViewById, só que desta vez utilizamos como
parâmetro a constante R.id.campoValorAlcool, e armazena-
remos esta referência na variável
Por fim, após a execução do método defineCampos, teremos
as duas variáveis campoPrecoGasolina, e campoPrecoAlco-
ol, as quais utilizaremos para pegar os valores para o cálculo.
8-4
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
nomes dos combustíveis, ou seja Álcool e Gasolina. Veja logo abai-
xo como fica definido este Enum.
8-5
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
Logo na linha 53 definimos o atributo GASOLINA, passando
como parâmetro a String Gasolina, e na sequência o atributo
ALCOOL, com a String, Álcool como parâmetro.
Para que possamos utilizar as representações do tipo
String dos atributos do enum, precisamos de sobrecarregar o
método toString.
Por isso, na linha 56 utilizamos a palavra-chave override,
e escrevemos o nome do método toString, informando que o seu
retorno é String, e no corpo do método apenas retornamos o va-
lor do atributo nome da classe enum.
Com isso temos tudo o que precisamos para definir a função
que vai fazer o cálculo do combustível mais indicado. Veremos isso
logo em seguida.
8-6
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
46| if (proporcao < fatorEscolha) {
47| return Combustivel.ALCOOL
48| } else {
49| return Combustivel.GASOLINA
50| }
51| }
8-7
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
É considerado uma boa prática no desenvolvimento de sof-
tware evitarmos usar valores literais diretamente na lógica, por
isso na linha 43, criamos a variável imutável chamada fatorEs-
colha, e atribuímos a essa variável o valor 0.7.
Na sequência, na linha 44, efetuamos a divisão entre os parâ-
metros precoAlcool e precoGasolina, o valor desta divisão será
armazenado na variável imutável que chamamos de proporcao.
Agora precisamos verificar se o valor da variável propoção,
é menor que o valor armazenado em fatorEscolha, fizemos isso
na linha 45, utilizando a expressão condicional determinada após
a palavra-chave if.
Caso o valor da expressão condicional for true, então o có-
digo da linha 46 será executado, e o valor retornado será o atributo
ALCOOL da classe enum Combustível. Caso contrário, se o valor
da expressão da linha 45, retornar o valor false, então o código
da linha 48 será executado, ou seja, o valor retornado por esse mé-
todo será o atributo GASOLINA, da classe enum Combustível.
Com isso, já temos um método que recebe os preços da ga-
solina e do álcool e retorna qual combustível é o mais vantajoso.
8-8
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
37|
val resultadoTextView = findViewById<-
TextView>(R.id.textCombustivel)
38| resultadoTextView.text = “O Combustível
indicado é ${resultado.toString()}”
39| }
8-9
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
campoPrecoGasolina e campoPrecoAlcool e usar estes va-
lores como parâmetros para chamar o método calculaMelhor-
Combustivel que vai retornar o atributo do enum Combustí-
vel que representa o combustível mais vantajoso.
Feito isto precisamos exibir ao usuário uma mensagem que
utiliza este valor, para isso faremos uma chamada para o méto-
do mostraResultado. Veja abaixo como ficou o código do mé-
todo defineBotao:
8-10
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
Lembre-se que estamos escrevendo o método que vai ser
executado quando o botão Calcular for clicado, neste caso, na
linha 27 precisamos pegar a referência do elemento do tipo But-
ton que possui o id, botaoCalcular, que está armazenado em
R.id.botaoCalcular, por isso utilizamos este valor como pa-
râmetro na chamada do método findViewById, e passamos como
tipo o valor Button entre os sinais de menor e maior.
Após a execução desta linha a referência para este elemento
do layout estará disponível na variável botaoCalcular. Veja que
na linha 28 utilizamos o método setOnClickListener de uma
maneira peculiar, veja que logo após o nome do método utilizamos
caractere abre chaves {, escrevemos o código e depois utilizamos o
caractere fecha chaves }, muito código foi simplificado nesta nota-
ção, e pode parecer meio estranho a primeira vista.
Se olharmos no detalhe a definição do método setOnCli-
ckListener, veremos que ele recebe um único parâmetro do tipo
((View) -> Unit), este tipo é uma função lambda, que recebe
como parâmetro um objeto do tipo View, e retorna o tipo Unit.
Em Kotlin, o tipo Unit, indica que a função não possui retorno.
Segundo a linguagem Kotlin, se um método recebe apenas
um parâmetro, e esse parâmetro é uma função, então podemos re-
mover os parênteses.
Outro ponto para simplificarmos é, que se a função lambda
passada como parâmetro não utiliza o seu próprio parâmetro, po-
demos remover todo o lado esquerdo da função, o que sobra então
é apenas o código do corpo da função lambda, ou seja precisamos
apenas usar as chaves e indicar o código da função, que no caso do
exemplo está escrito nas linhas 29 até a 32.
Na linha 29 utilizamos a referência para o campo onde ar-
mazenamos o preço do álcool e acessamos o atributo text, é neste
8-11
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
atributo que estará o valor do preço do álcool informado pelo usu-
ário, atente ao fato de que o tipo deste atributo é String, ou seja,
precisamos converter este tipo para Double, pois iremos efetuar
uma operação de divisão logo abaixo, e não podemos dividir um
número do tipo String.
O mesmo faremos na linha 30, com a referência ao campo
onde o usuário vai entrar o valor da gasolina, ou seja utilizaremos
atributo text, só que agora da variável campoPrecoGasolina,
converteremos este valor para o tipo Double, e armazenaremos
ele na variável precoGasolina.
Agora que já temos os dois valores dos preços da gasolina e
do álcool, podemos chamar a função calculaMelhorCombus-
tivel, para obter como resposta qual é o combustível mais vanta-
joso, no formato do enum Combustível, e armazenaremos este
valor na variável combustível.
Por fim, utilizaremos a variável combustível como parâ-
metro para o método mostraResultado, feito isso, o objeto do
tipo TextView, será atualizado com a mensagem que informa
qual o combustível é mais vantajoso.
8-12
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
14| override fun onCreate(savedInstanceSta-
te: Bundle?) {
15| super.onCreate(savedInstanceState)
16| setContentView(R.layout.activity_main)
17| defineCampos()
18| defineBotao()
19| }
8-13
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 8
C O D IFIC A N D O A ACTI VI TY
Figura 8-1: Aplicativo calcula combustível
8-14
EXERCÍCIOS PROPOSTOS
8-15
3) Escolha a alternativa correta sobre o método defineCampos que foi escri-
EX ER C ÍC IO S PR O PO STO S
to na classe MainActivity.
8-16
11| return nome
12| }
EX ER C ÍC IO S PR O PO STO S
13| }
( ) -a) Não podemos marcar este método como private, pois vamos
utilizar ele dentro da classe MainActivity.
8-17
( ) -b) Não é uma boa prática utilizarmos o valor do tipo enum
como retorno do método.
EX ER C ÍC IO S PR O PO STO S
( ) -c) Como o tipo da variável proporcao, não foi definido, ele sem-
pre será do tipo Int.
( ) -d) Este método calcula qual é o combustível mais vantajoso,
retornando como valor o tipo Combustivel que é um enum
com dois valores possíveis ALCOOL ou GASOLINA.
( ) -e) A variável fatorEscolha não pode ser declarada com o modi-
ficador val.
8-18
7) Considere o código abaixo e escolha a alternativa correta:
EX ER C ÍC IO S PR O PO STO S
1| private fun defineBotao() {
2| val botaoCalcular = findViewById<But-
ton>(R.id.botaoCalcular)
3| botaoCalcular.setOnClickListener {
4| val precoAlcool = campoPrecoAlcool.
text.toString().toDouble()
5| val precoGasolina = campoPrecoGasoli-
na.text.toString().toDouble()
6| val combustivel = calcularMelhorCom-
bustivel (precoGasolina,precoAlcool)
7| mostraResultado(combustivel)
8| }
9| }
8-19
8) Considere o método onCreate sobrescrito abaixo e escolha a afirmação
EX ER C ÍC IO S PR O PO STO S
correta.
8-20
( ) -c) Devemos definir o clique do botão pelo método setOnCli-
ckListener, passando uma outra classe que vai receber o
EX ER C ÍC IO S PR O PO STO S
evento
( ) -d) Devemos definir o clique do botão pelo método setOnCli-
ckListener, passando uma função lambda que será executa-
da quando o evento acontecer.
( ) -e) Devemos definir o atributo clickable como true.
10) Escolha a alternativa que contém o método correto que carrega os ele-
mentos do layout definidos no arquivo .xml
( ) -a) Super.onCreate(savedInstance)
( ) -b) FindViewById<EditText>(R.id.campoValorGasolina)
( ) -c) FindViewById<EditText>(R.id.campoValorAlcool)
( ) -d) SetContentView(R.layout.activity_main.xml)
( ) -e) SetContentView(R.layout.activity_main)
8-21
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
UNIDADE 5:
SEGUNDO APLICATIVO:
LISTA DE COMPRAS
Caro(a) Aluno(a)
Seja bem-vindo(a)!
Ótimos estudos!
Conteúdos da Unidade:
Apresentação da arquitetura MVC, Definição do modelo de
dados, Definição da célula da lista de itens, Criação do ViewHol-
der da RecyclerView, Definição e uso de Intents, Criação do
Adapter da RecyclerView, Criação da Activity para inclusão de
novos itens, Criação da Activity para a visualização de itens já
inclusos, Introdução ao arquivo Android Manifest.
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
CAPÍTULO 9:
RECYCLERVIEW E RECYCLERADAPTER
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-3
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-4
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9.3.1 Modelo
Consideremos os elementos do grupo Modelo, como sendo
as entidades que representam os dados que o nosso aplicativo uti-
liza. No caso do aplicativo lista de compras, teremos uma classe
chamada ItemLista, que possuirá os atributos, qtd do tipo Int,
nome do tipo String e comprado do tipo Boolean, que vai indi-
car se o item já foi comprado ou não.
O objetivo do nosso aplicativo é possibilitar ao usuário um
meio de cadastrar novos itens de compra e exibi-los em uma tabela
na tela inicial do aplicativo.
9.3.2 Controlador
Para exibir os dados cadastrados no modelo precisamos
de um elemento que chamaremos de Controlador, no Android,
9-5
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9.3.3 Visualização
Os controladores, por si só, não exibem os dados e neces-
sitam de elementos gráficos, tais como campos de texto, botões,
listas entre outros para exibir os dados dos modelos.
Ao conjunto destes elementos chamamos de visualização e
no caso da plataforma Android, são comumente descritos em ar-
quivos do tipo xml, que ficam organizados na pasta layout que por
sua vez fica dentro da pasta res.
No caso do aplicativo que vamos desenvolver neste capítulo,
podemos considerar os campos que vão receber o nome e a quan-
tidade dos itens como sendo parte dos elementos de visualização.
9-6
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
1| package com.segundo.listadecompras.modelo
2|
3| data class ItemLista(val qtd: Int,
4| val nome: String,
5| var comprado: Boolean) {
6|
7| }
9-7
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
1| package com.segundo.listadecompras.modelo
2|
3| object ListaDeCompras {
4|
5| var listaItens = mutableListOf<ItemLista>()
6|
7| fun adicionarItemNaLista(item: ItemLista) {
8| listaItens.add(item)
9-8
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-9
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-10
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-11
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-12
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-13
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-14
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-15
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-16
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-17
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-18
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-19
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-20
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-21
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-22
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-23
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-24
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-25
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-26
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-27
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-28
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-29
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 9
9-30
EXERCÍCIOS PROPOSTOS
9-31
4) Escolha a alternativa correta sobre a classe LinhaLista:
EX ER C ÍC IO S PR O PO STO S
( ) -a) A classe LinhaLista faz parte do modelo do aplicativo lista
de compras.
( ) -b) A classe LinhaLista é do tipo RecycleView.ViewHolder, ou
seja, ela representa o código de cada uma das linhas que se-
rão exibidas pela RecycleView.
( ) -c) A classe LinhaLista é o adapter da classe RecyclerView que
vai exibir as linhas dos itens da lista de compras.
( ) -d) Não podemos acessar o modelo diretamente pela classe
LinhaLista.
( ) -e) N.d.a
9-32
( ) -a) A classe foi declarada de maneira errada pois os dados dos
parâmetros deveriam ter sido armazenados nos atributos de
EX ER C ÍC IO S PR O PO STO S
mesmo nome.
( ) -b) O parâmetro comprado, deveria ter sido marcado com a pa-
lavra chave val.
( ) -c) Na linha 3 o parâmetro comprado foi corretamente marcado
com a palavra chave var pois este parâmetro será modificado
e deverá ser mutável.
( ) -d) A palavra chave data não está definida na linguagem Kotlin.
( ) -e) N.d.a.
9-33
8) Sobre o método onResume escolha a alternativa correta:
EX ER C ÍC IO S PR O PO STO S
1| override fun onResume() {
2| super.onResume()
3| atualizaListaDeCompra()
4| }
( ) -a) LinearLayoutManager
( ) -b) RecyclerView
( ) -c) FloatingActionButton
( ) -d) TextView
( ) -e) AppCompatActivity
( ) -a) Data
( ) -b) Open
( ) -c) Private
( ) -d) Model
( ) -e) Public
9-34
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
CAPÍTULO 10:
VISUALIZANDO E ADICIONANDO ITENS
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
10.1 Introdução
Neste capítulo vamos criar a Activity que possibilitará ao
usuário incluir novos itens em sua lista de compras, está Acti-
vity será lançada assim que o usuário clicar no botão com ícone
da imagem do símbolo positivo que está no canto inferior direito
da MainActivity.
Mostraremos também neste capítulo como vai ser escrita
a Activity que o usuário vai utilizar para marcar o item como
comprado, esta Activity será lançada quando o usuário clicar na
linha da tabela.
10-2
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
Figura 10-1: Layout da Activity para a inclusão de novos itens
10-3
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
id. Adicione uma restrição de layout de valor 16 ao topo da view
pai, e uma restrição de valor 16 da borda esquerda da view pai.
Temos agora que adicionar o elemento do tipo EditText,
este elemento vai ser responsável por receber o texto referente ao
nome do item que vai ser inserido na lista de compra.
Como teremos que acessar o conteúdo que o usuário digitou,
para guardar no modelo e posteriormente mostrar na lista, vamos
modificar o id deste elemento para itemNomeEditText.
Para que o campo ocupe todo o espaço horizontal menos o
espaço ocupado pelas restrições de layout, modifique o atributo
layout_width para 0dp.
Modifique também o atributo minHeight para 48dp, por
fim coloque uma restrição de valor 16 com relação ao lado esquer-
do da view pai, outra de tamanho 16 com relação ao lado es-
querdo da view pai e por fim uma restrição de tamanho 8 com
relação ao TextView que criamos no passo anterior.
Temos agora que incluir um elemento do tipo TextView que
vai mostrar ao usuário o texto Quantidade, para isso modifique o
atributo text, para este valor.
Não precisamos alterar o atributo id deste elemento pois
não será necessário acessar nenhuma propriedade dele através da
Activity. Modifique o atributo textSize, deste elemento para
20sp, e adicione uma restrição de layout de valor 32, que tenha
relação com o campo texto do passo anterior e mais uma restrição
de layout com relação ao lado esquerdo da view pai, que pos-
sua valor 16.
Precisamos agora de um campo onde o usuário vai inserir
a quantidade do item que deverá ser comprado, para isso insira
no layout um elemento do tipo EditText, mude a propriedade
10-4
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
inputType para number, pois só receberemos valores numéri-
cos inteiros.
Para este campo deveremos modificar o atributo id, pois
iremos pegar o valor que o usuário digitou e armazenar no mode-
lo. Vamos então inserir neste campo o valor itemQtdEditText.
Modifique também o atributo minHeight para 48dp assim vamos
garantir que o campo sempre possua um tamanho mínimo razoá-
vel para que o usuário consiga entrar com o valor.
Por fim, crie uma restrição de layout de valor 8 que aponte
para o elemento que representa o texto Quantidade, e outra restri-
ção de layout apontando para o lado esquerdo da view que con-
tém este elemento, com valor de 16.
O último elemento que vamos inserir neste layout vai ser do
tipo Button, arraste um novo elemento deste tipo para o editor de
layout e modifique seu atributo text para o texto salvar.
Precisamos pegar o evento de clique neste botão, portanto
precisaremos de uma referência para este elemento na Activity
que vai exibir esse layout, para isso modifique o atributo id, para
o texto salvarButton.
Crie uma restrição de layout de tamanho 16 com o lado es-
querdo da view que contém este objeto, e outra restrição de layout
de tamanho 32 relacionando campo onde o usuário vai entrar com
o valor da quantidade. Veja na figura abaixo como deverá ficar as
restrições de layout ao final do processo.
10-5
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
Figura 10-2: Restrições de layout.
10-6
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
Toda a Activity do aplicativo Android deverá estar re-
gistrada no arquivo chamado AndroidManifest.xml, que fica
dentro da pasta manifests. Todo projeto de aplicativo Android
precisa ter um arquivo AndroidManifest, é nele onde estão rela-
cionadas informações específicas do aplicativo que são necessárias
tanto em tempo de compilação quanto em tempo de execução.
Essas informações vão do nome do ícone, até permissões
para o uso da câmera e da localização. As Activitys também de-
vem estar descritas neste arquivo, inclusive a MainActivity que
recebe um parâmetro especial que vai indicar ao Android que é
essa tela que deverá aparecer quando o usuário abrir a aplicação.
Para melhorar a leitura, vamos mostrar abaixo apenas as linhas do
arquivo AndroidManifest que são necessárias para registrar a
nova Activity que estamos criando.
10-7
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
18| :
19| :
27| </application>
28|
29| </manifest>
10-8
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
15|
setContentView(R.layout.
activity_adiciona_item)
16| defineBotaoSalvar()
17| }
18|
19| :
20| :
21|
22| }
10-9
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
19| private fun defineBotaoSalvar() {
20|
val botaoSalvar = findViewById<But-
ton>(R.id.salvarButton)
21| botaoSalvar.setOnClickListener {
22| val item = criaItemLista()
ListaDeCompras.adicionarItemNaLista(item)
23|
24| finish()
25| }
26| }
10-10
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
Na linha 22 vamos chamar o método criaItemLista, este
método ainda não foi definido, mas vai ser responsável por pegar
os dados dos campos, criar um novo objeto do tipo ItemLista
com estes dados e retornar este objeto, ou seja, a variável imutá-
vel item, já possuirá os dados que foram entrados pelo usuário.
Por isso na linha 23 apenas incluímos este novo objeto na lista de
compras chamando o método adicionaItemLista, fazendo isso
diretamente da referência da classe ListaDeCompras que mar-
camos com o modificador object, ou seja, estamos utilizando o
padrão Singleton para fazer essa chamada.
Feito isso, já temos o nosso novo item adicionado na lista de
compras e podemos terminar a AdicionaItemActivity, para
isso na linha 24 chamamos o método finish, lembre-se que este
método foi herdado da classe AppCompatActivity.
Para terminarmos a classe AdicionaItemActivity, só
precisamos escrever o método criaItemLista, veja abaixo
como ficou:
10-11
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
Como dito anteriormente o objetivo deste método é pegar os
dados dos campos e criar um objeto do tipo ItemLista, para isso
na linha 29 definimos a variável imutável itemNomeTextView,
utilizamos o método findViewById, passamos como parâmetro o
tipo do elemento que vamos procurar no layout que neste caso é o
EditText, e passamos como parâmetro a constante R.id.item-
NomeEditText, onde está armazenado o id que criamos para o
campo onde o usuário vai entrar o nome do item.
Na sequência fazemos o mesmo para o campo, onde o usu-
ário entrará com o valor da quantidade do item, utilizaremos no-
vamente o método findViewById, porém desta vez mudaremos
o parâmetro para a constante que faz referência o campo onde o
usuário vai entrar com a quantidade, por isso usamos a constante
R.id.itemQtdEditTExt.
A referência para este campo vai ficar armazenada na variá-
vel imutável chamada itemQtdTextView.
Chegou a hora de extrairmos os dados de cada uma das refe-
rências dos campos, na linha 31, começamos por pegar o nome do
item, para isso vamos utilizar a referência para o campo item nome
que está armazenada na variável imutável itemNomeTextView,
este dado está disponível no atributo text dessa variável.
Perceba que o tipo do atributo text não é String, por
isso precisaremos utilizar o método toString para fazer a con-
versão, armazenaremos este valor na variável imutável cha-
mada itemNome.
Faremos o mesmo com o valor da quantidade que foi en-
trada no campo da referência itemQtdTextView, novamente
teremos que primeiro converter o valor do atributo text, deste
campo para o tipo String, portanto novamente faremos uso do
método toString.
10-12
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
Mas lembre-se que no modelo o atributo que representa a
quantidade é do tipo Int, ou seja, novamente teremos que fazer
uma nova conversão para este tipo, utilizando o método toInt.
Feito isto temos os dados extraídos dos campos e armazena-
dos nas variáveis imutáveis itemNome e itemQtd, agora preci-
samos criar o novo objeto do tipo ItemLista, para isso na linha
33 chamamos o construtor do objeto passando como primeiro pa-
râmetro a variável itemQtd, como segundo parâmetro a variável
itemNome e por fim vamos marcar este item que acabou de ser
incluído como não comprado ainda, ou seja, passaremos o valor
false para este último parâmetro. Com isso terminamos a imple-
mentação da AdicionaItemActivity.
10-13
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
Figura 10-3: Layout da visualização do Item
10-14
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
elemento no código, por isso vamos mudar o valor da propriedade
id para itemNomeTextView.
Modifique também o atributo textSize para o valor 32sp.
Vamos colocar uma restrição de layout que vai centralizar este ele-
mento horizontalmente e uma outra restrição que vai gerar uma
margem com valor de 96 do topo da view que contém este elemento.
Este layout precisará de mais um elemento do tipo Button,
novamente, como precisaremos definir o evento de clique neste
botão precisaremos de uma referência dele no código, para isso
vamos mudar o valor do atributo id para compradoButton.
Devemos também mudar o título deste botão para o texto
comprado. Por fim crie duas restrições de layout uma que fará um
distanciamento de 96 do elemento TextView criado anteriormen-
te e outra que vai centralizar este elemento do tipo Button hori-
zontalmente dentro da view container.
10-15
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
13|
override fun onCreate(savedInstanceS-
tate: Bundle?) {
14| super.onCreate(savedInstanceState)
15|
setContentView(R.layout.
activity_visualiza_item)
16|
itemIndice = intent.extras?.getInt
(“itemIndice”,0)
17| pegaNomeDoItem()
18| defineBotaoComprado()
19| }
20| :
21| :
22| }
10-16
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
constante R.layout.activity_visualiza_item. Passaremos
esta constante como parâmetro para o método setContentView.
Quando a VisualizaItemActivity é inicializada pela
MainActivity por meio da classe LinhaLista, temos na linha
27 desta classe a chamada para o método putExtra, recapitulan-
do, utilizamos este método para armazenar o valor da posição da
lista que foi clicado usando a chave itemIndice, logo na linha
16, da activity VisualizaItemActivity vamos acessar este
valor por meio do método getInt do atributo intent.extras
da Activity.
Vale a pena notar que utilizamos o símbolo ?, na chamada do
método getInt, isso significa que estamos fazendo uma chamada
segura ao método, esse termo é conhecido em inglês como sendo
uma safe call.
Isso acontece pois o valor do atributo extras, pode ser nulo,
e fazendo uso do operador ?, estamos dizendo ao compilador que
se o atributo extras for nulo então qualquer operação com este
atributo vai retornar nulo.
Antigamente, quando usávamos a linguagem java, o opera-
dor de chamada segura não existia e muitos erros do tipo Null-
PointerException, atormentavam a vida dos programadores,
como a linguagem Kotlin implementa o operador de chamada se-
gura, temos uma proteção para este tipo de situação.
Como estamos seguros de que a chave é a mesma que utili-
zamos quando chamamos o método putExtra, então neste caso
este valor nunca será nulo, porém como o compilador não pode
garantir isso, temos que usar o operador?.
Depois da linha 16 já temos definido o valor da variável ite-
mIndice, e ele poderá ser usado mais adiante. Após isso na linha
10-17
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
17 fizemos uma chamada ao método pegaNomeDoItem, que será
definido mais adiante, e terá como objetivo pegar o nome do item
do modelo e colocar esse valor no campo text do elemento Tex-
tView que criamos anteriormente no layout.
E na linha 18, chamamos o método defineBotaoComprado,
que vai fazer com que quando o usuário clique no botão comprado,
o item seja marcado como comprado.
Vamos agora escrever o método pegaNomeDoItem, veja
como ficou logo abaixo:
10-18
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
Este código retorna o valor da variável ItemIndice caso
esse valor não seja nulo e caso contrário vai retornar o valor 0, cha-
mamos este operador de Elvis Operator, pois ele lembra o topete
do cantor Elvis Presley.
Feito isso pegamos o atributo nome deste elemento e arma-
zenamos no atributo text da variável nomeItemTextview, que
representa o elemento de layout do tipo TextView que vamos uti-
lizar para exibir o nome do item.
Vamos agora escrever o último método desta classe, que será
o defineBotaoComprado, veja abaixo como vai ficar:
10-19
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
Logo no começo definimos a variável botaoComprado,
que vai armazenar uma referência para o elemento do layout
do tipo Button, ao qual modificamos o id para comprado-
Button, para isso utilizamos mais uma vez o método find-
ViewById, passando o tipo Button e como parâmetro a constan-
te R.id.compradoButton.
Precisaremos também de uma referência para o item que
será marcado como comprado, por isso na linha 29 definimos a
variável itemComprado, novamente acessamos o atributo lis-
taItens diretamente da classe ListaDeCompras e passamos
como índice do item da lista a variável itemIndice, veja que no-
vamente utilizamos o operador?: que vai retornar 0 caso o valor da
variável itemIndice seja nulo.
Por fim pegamos o valor do atributo comprado, e teremos
então o valor deste atributo na variável itemComprado, lembre-
-se que este atributo é do tipo Boolean, ou seja, poderemos ter os
valores True ou False apenas.
Temos como objetivo, mudar o título do botão para o texto
Desfazer, caso o item já tenha sido comprado e caso o item não
tenha sido comprado vamos mudar o título deste botão para com-
prado, ou seja, o usuário poderá desmarcar o item caso ele mude
de ideia.
Portanto na linha 30, escrevemos uma condição que verifica
o valor da variável itemComprado é True, se for, retornamos a
String Desfazer, caso contrário se o valor da variável itemCom-
prado for False, então retornaremos a String Comprado, este
valor será armazenado na variável tituloBotao, e será atribuído
logo abaixo na linha 32 para a propriedade text do botão, fazendo
com que seu título mude conforme sua função.
10-20
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
Temos agora que atribuir a função lambda que vai ser exe-
cutada quando o botão for clicado pelo usuário, faremos isso cha-
mando o método setOnClickListener e passando como pa-
râmetro a função definida pelas linhas 34, onde fazemos uso da
classe ListaDeCompras para acessar o atributo listaItens,
novamente utilizamos a variável itemIndice que possui o valor
do índice do elemento na lista juntamente com o operador ?:, e
modificamos o atributo comprado do elemento para a negação do
valor Booleano armazenado na variável itemComprado.
Neste caso, se o item já foi comprado, a variável itemCom-
prado possuirá valor True, como usamos o operador ! Estamos
mudando esse valor para False, ou seja, estamos desfazen-
do a compra.
Caso contrário, se o valor da variável itemComprado for
False, estaremos armazenando True no atributo comprado do
elemento, de maneira a marcar o elemento como comprado.
A última tarefa que esta função lambda vai executar é o mé-
todo finish, que irá terminar a VisualizaItemActivity.
10-21
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
1| private fun defineBotaoAdicionaItem() {
2|
val adicionaItemFloatButton = find-
ViewById<FloatingActionButton>(R.
id.adicionaItemFloatButton)
3| adicionaItemFloatButton.setOnClickListener {
4|
val adcionaItemIntent = Intent(this,
AdicionaItemActivity::class.java)
5| startActivity(adcionaItemIntent)
6| }
7| }
10-22
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
reflexão e retorna uma referência para a classe que estamos usan-
do como operando, isso fará com que o objeto adicionaItemIn-
tent, fique associado a AdicionaItemAcitvity, por fim bas-
ta chamarmos o método startActivity, como feito na linha 5
para lançarmos a AdicionaItemActivity.
10-23
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
parâmetro a constante que faz referência a esse elemento que é a
R.id.removerTodosFloatButton.
Com esta referência armazenada na variável imutável cha-
mada removeTodosFloatButton, chamamos o método setOn-
ClickListener, e passamos como parâmetro a função lambda
definida nas linhas 4 e 5.
Já na linha 4 chamamos o método removerTodosItens da
classe ListaDeCompras que é um singleton e na sequência,
na linha 5 chamamos o método atualizaListaDeCompra, para
que a listaDecomprasRecycleView, seja atualizada e os itens
não sejam mais mostrados.
10-24
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 10
V IS U A LIZA N D O E A D IC IO N AN D O ITEN S
Toda a vez que o usuário abrir o aplicativo o método on-
Create da MainActivity será executado, na linha 3, o
método cria todos os elementos que foram definidos no ar-
quivo activity_main.xml.
É neste método que precisamos criar uma referência para
o elemento do tipo RecyclerView que foi definido no layout,
para isso utilizamos o método findViewById e passamos como
parâmetro a constante R.id.listaDeComprasRecyclerView,
que faz referência a esse elemento.
Armazenaremos esta referência no atributo de classe chama-
do listaDecomprasRecycleView. Feito isso, precisamos ainda
definir a ação para o botão que adiciona um item na lista e para
o botão que remove todos os itens da lista, por isso chamamos o
método defineBotaoAdicionaItem na linha 5 e o método de-
fineBotaoRemovertodos na linha 6.
10-25
EXERCÍCIOS PROPOSTOS
10-26
3) Sobre o arquivo AndroidManifest.xml escolha a alternativa correta
EX ER C ÍC IO S PR O PO STO S
( ) -a) Este arquivo não é necessário e pode ser apagado do projeto.
( ) -b) Não é necessário registrarmos neste arquivo as Activities do
aplicativo.
( ) -c) Todo projeto Android possui um arquivo chamado Android-
Manifest.xml, neste arquivo é declarada a MainActivity e as
outras Activities, permissões sobre o uso da câmera e das
bibliotecas de localização também são declaradas neste
arquivo.
( ) -d) Este arquivo não é criado automaticamente pelo Android
Studio.
( ) -e) Este arquivo não pode ser lido, pois seu formato é binário.
( ) -a) App/res
( ) -b) App/res/layout
( ) -c) App/res/values
( ) -d) App/manifests
( ) -e) App/mipmap
( ) -a) O código acima não possui nenhum erro, e vai ser executado
assim que a Activity for lançada.
( ) -b) O código acima possui apenas um erro, pois a palavra chave
override precisa vir antes da palavra fun na linha 1
10-27
( ) -c) O código acima possui apenas um erro, pois ele deve chamar
o método setContentView para instanciar os elementos que
EX ER C ÍC IO S PR O PO STO S
foram definidos no arquivo activity_adiciona_item.xml.
( ) -d) O código acima possui dois erros, na linha 1 antes da palavra
chave fun precisamos marcar o método com a palavra chave
override e logo após a linha 2 devemos inserir uma chamada
para o método setContentView, passando como referência a
constante R.layout.activity_adiciona_item.
( ) -e) N.d.a.
( ) -a) Text
( ) -b) Id
( ) -c) AutoText
( ) -d) Capitalize
( ) -e) TextSize
1| botaoComprado.setOnClickListener {
10-28
2| ListaDeCompras
.listaItens[itemIndice ?: 0]
EX ER C ÍC IO S PR O PO STO S
.comprado = !itemComprado
3| finish()
4| }
( ) -a) O código acima está errado pois devemos usar apenas pa-
rênteses para passarmos os parâmetros e não chaves.
( ) -b) O método finish não foi implementado, e vai causar um erro
de compilação.
( ) -c) O código acima faz com que quando o botão comprado do
layout receber um clique o item irá mudar o seu estado
de comprado para true caso ele seja false e para false caso
ele seja true e a VisualizaItemActivity vai continuar sendo
apresentada.
( ) -d) O código acima faz com que quando o botão comprado do
layout receber um clique o item irá mudar o seu estado de
comprado para true caso ele seja false e para false caso ele
seja true e a VisualizaItemActivity vai ser fechada pois o mé-
todo finish foi chamado na linha 3.
( ) -e) N.d.a.
10-29
na linha 3 modifica o atributo text para ter o valor do nome
do item que foi selecionado na lista da MainActivity.
EX ER C ÍC IO S PR O PO STO S
( ) -c) Não podemos definir a variável nomeItemTextView com a
palavra chave val, pois vamos modificar o atributo text na
linha 3.
( ) -d) Não precisamos usar o operador ?: pois a variável itemIndi-
ce nunca vai ser nula.
( ) -e) Não podemos definir o método pegaNomeDoItem como pri-
vate pois este método será chamado pela MainActivity.
10-30
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
UNIDADE 6:
PERSISTÊNCIA NO APLICATIVO LISTA
DE COMPRAS
Caro(a) Aluno(a)
Seja bem-vindo(a)!
Ótimos estudos!
Conteúdos da Unidade:
Adicionando suporte para a biblioteca Room, Criando modelo
de dados, Criando o Data Access Object, Criando a classe Room-
DataBase, Apresentando o objeto Executor, Apresentando o ob-
jeto Handler, Criando um parâmetro lambda para uma função,
Introdução ao conceito de Threads.
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
CAPÍTULO 11:
CRIANDO A CAMADA DE PERSISTÊNCIA
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 11
C R IA N D O A C A MA D A D E PER SISTÊ N CI A
11.1 Introdução
Quando inserimos alguns itens no aplicativo desenvolvido
na unidade anterior e em seguida fechamos este aplicativo perce-
beremos que todos os itens inseridos vão desaparecer.
Isso acontece pois estamos mantendo os dados cadastrado
na lista apenas em memória, pois olhando o código, veremos que
os itens da lista estão todos armazenados no atributo listaI-
tens, da classe ListaDeCompras, consequentemente, quando o
aplicativo sai da memória RAM do dispositivo, esta lista será desa-
locada, e os dados serão perdidos para sempre.
Para adicionar a funcionalidade de persistir os dados do apli-
cativo vamos fazer uso da biblioteca do android chamada Room.
Esta biblioteca fornece um mapeamento entre objetos definidos na
memória e tabelas em um banco de dados, este tipo de funcionali-
dade é chamado de ORM (Object Relational Map).
1| plugins {
2| id ‘com.android.application’
3| id ‘kotlin-android’
4| id ‘kotlin-kapt’
5| id ‘kotlin-android-extensions’
6| }
11-3
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 11
C R IA N D O A C A MA D A D E PER SISTÊ N CI A
Depois de feita essa modificação clique no quinto contando da
direita para a esquerda na barra de ferramentas do Android Studio, o
hint deste botão é “Sync Project With Gradle Files”, isso
é necessário pois o Gradle vai baixar as dependências necessárias.
Além da secção plugins, devemos também modificar a
secção dependencies adicionando as duas últimas linhas, como
mostrado abaixo:
1| dependencies {
2|
implementation ‘androidx.core:core-ktx:1.6.0’
3|
4| implementation ‘androidx.
appcompat:appcompat:1.3.1’
5| implementation ‘com.google.android.
material:material:1.4.0’
6| implementation ‘androidx.cons-
traintlayout:constraintlayout: 2.1.1’
7| testImplementation ‘junit:junit:4.+’
8| androidTestImplementation ‘androidx.
test.ext:junit:1.1.3’
9| androidTestImplementation ‘androidx.
test.espresso:espresso-core:3.4.0’
implementation ‘androidx.room:room-ktx:2.3.0’
10|
11| kapt “androidx.room:room-compiler:2.3.0”
12| }
11-4
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 11
C R IA N D O A C A MA D A D E PER SISTÊ N CI A
Como dito anteriormente clique no quinto botão da direita
para esquerda que contém o hint “Sync Project With Gra-
dle Files”.
1| @Entity
2| data class Item(@NonNull
3| @PrimaryKey(autoGenerate = true)
4| var id: Long?,
5| val qtd: Int,
6| val nome: String,
11-5
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 11
C R IA N D O A C A MA D A D E PER SISTÊ N CI A
7| var comprado: Boolean) {
8| }
11-6
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 11
C R IA N D O A C A MA D A D E PER SISTÊ N CI A
11.4 Adicionando o Data Access Object
É também exigido pela biblioteca Room que criemos uma in-
terface para representar o DAO que significa Data Access Ob-
ject, é por meio desta classe que a biblioteca Room vai fazer as
operações de inclusão, alteração, remoção e leitura dos dados ar-
mazenados no banco.
É muito comum darmos a essas operações o nome de CRUD,
que na língua inglesa significa Create, Read, Update e Delete.
Para isso vamos criar uma interface chamada ItemDao, no pacote
modelo do projeto e escrever o seguinte código:
1| @Dao
2| interface ItemDao {
3|
4| @Insert
5| fun insere(item: Item)
6|
7|
@Query(“SELECT * from Item order by
nome asc”)
8| fun pegaTodosItens(): MutableList<Item>
9|
10| @Query(“DELETE from Item”)
11| fun deleteTodos()
12|
13|
@Query(“UPDATE Item SET comprado=:com-
prado WHERE id = :id”)
11-7
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 11
C R IA N D O A C A MA D A D E PER SISTÊ N CI A
14|
fun atualizaItem(comprado: Boolean, id: Long)
15| }
11-8
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 11
C R IA N D O A C A MA D A D E PER SISTÊ N CI A
atualizaItem, que vai receber como primeiro parâmetro um
tipo Boolean indicado se o item foi comprado ou não, e como se-
gundo parâmetro o id do item.
1|
@Database(entities = [Item::class], version = 1)
2| abstract class ItemDataBase: RoomDatabase() {
3|
4| abstract fun itemDao(): ItemDao
5|
6| companion object {
private var INSTANCIA: ItemDataBase? = null
7|
8|
fun pegaInstancia(context: Context):
ItemDataBase? {
9| if (INSTANCIA == null) {
10|
synchronized(ItemDataBase::class) {
11|
INSTANCIA = Room.databaseBuilder
(context.applicationContext,
12| ItemDataBase::class.java,
13| “item.db”).build()
11-9
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 11
C R IA N D O A C A MA D A D E PER SISTÊ N CI A
14| }
15| }
16| return INSTANCIA
17| }
18| }
19| }
11-10
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 11
C R IA N D O A C A MA D A D E PER SISTÊ N CI A
Na sequência vamos definir o método pegaInstancia, este
método será responsável por criar apenas uma instância da classe
ItemDataBase, e armazenar a referência para essa instância na
variável INSTANCIA.
Dentro do método pegaInstancia, temos uma condição
que verifica se a variável INSTANCIA é nula, caso isso seja verda-
deiro, então uma instância da classe ItemDataBase será criada,
quando chamamos o método databaseBuilder da classe Room,
passando como primeiro parâmetro o context, que foi recebido
no método pegaInstancia.
O segundo parâmetro do databaseBuilder é a referência
da classe ItemDataBase, que passamos usando o operador refle-
xivo e por fim passamos a String item.db, que vai dar nome ao
arquivo do SQLite que será criado no dispositivo para armazenar
o banco de dados.
Caso contrário, na linha 9, se a expressão condicional retor-
nar o valor false, então sabemos que a variável INSTANCIA, já
possui uma referência para um objeto do tipo ItemDataBase,
portanto um novo objeto deste tipo não precisa ser instanciado,
o método pegaInstancia, apenas precisa retornar este objeto,
como é feito na linha 16.
No próximo capítulo iremos ver como usar toda essa nova
infraestrutura de persistência que foi criada, para armazenar os
itens de uma lista. Da mesma maneira como foi feita neste capítulo
iremos modificar uma parte do aplicativo lista de compras.
11-11
EXERCÍCIOS PROPOSTOS
11-12
4) Sobre a anotação @Dao, escolha a alternativa correta.
EX ER C ÍC IO S PR O PO STO S
( ) -a) Marcamos uma interface com esta anotação para que a bi-
blioteca Room utilize-a para manipular os dados, ou seja,
para que as funcionalidades do CRUD sejam feitas.
( ) -b) A anotação @Dao é utilizada pela biblioteca Room para
marcar uma classe que será considerada como uma tabela.
( ) -c) A sigla Dao significa, Data Alteration Object.
( ) -d) Não podemos utilizar a anotação @Query dentro da interfa-
ce marcada com a anotação @Dao
( ) -e) O elemento marcado com a anotação @Dao não pode ser
uma interface.
11-13
6) Sobre a classe ItemDataBase escolha a alternativa verdadeira:
EX ER C ÍC IO S PR O PO STO S
( ) -a) Não precisamos marcar esta classe com a anotação @
Database.
( ) -b) Não é necessário termos uma referência para a interface
marcada com a anotação @Dao nesta classe.
( ) -c) Esta classe não é um singleton.
( ) -d) Esta classe é responsável por construir, versionar e dar aces-
so ao banco de dados que será armazendo num arquivo do
tipo SQLite.
( ) -e) Para construirmos uma instância desta classe chamamos o
método estático databaseBuilder, que não precisa de uma
referência do application context.
( ) -a) Esta anotação não pode ser utilizada na classe marcada pela
anotação @Entity
( ) -b) O parâmetro autoGenerate = true, força que o aplicativo cui-
da do id da chave primária da tabela, de maneira a nunca
repetir este valor entre os registros cadastrados.
( ) -c) A anotação @PrimaryKey(autoGenerate = true), garante
que o atributo id da tabela seja a chave primária e seu valor
auto gerado pelo banco de dados, de maneira que a aplica-
ção fique livre de controlar a lógica para esta finalidade.
( ) -d) Apenas a anotação @PrimaryKey é necessária para que o
campo id seja considerado como chave primária e para que
seu valor seja auto gerado.
( ) -e) A anotação PrimaryKey não pertence à biblioteca Room.
1| plugins {
2| :
3| :
11-14
4| id ‘kotlin-kapt’
5| id ‘kotlin-android-extensions’
EX ER C ÍC IO S PR O PO STO S
6| }
7| :
8| :
36| dependencies {
37| :
38| :
45| implementation ‘androidx.room:room-ktx:2.3.0’
46| kapt “androidx.room:room-compiler:2.3.0”
47| }
11-15
( ) -c) A o texto que representa o código SQL na linha 1 está errado,
o correto seria: SELECT * from itemDatabase
EX ER C ÍC IO S PR O PO STO S
( ) -d) Devemos escrever uma classe ItemDao que vai implementar
a interface ItemDao.
( ) -e) N.d.a.
11-16
DISCIPLINA:
Desenvolvimento de Aplicativos
para Dispositivos Móveis
CAPÍTULO 12:
INTEGRANDO A CAMADA
DE PERSISTÊNCIA
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-2
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
8| object ListaDeCompras {
9|
10| var listaItens = mutableListOf<Item>()
11|
12|
private val executor = Execu-
tors.newSingleThreadExecutor()
13|
private val handler = Handler(Loo-
per.getMainLooper())
14| :
15| :
16| }
12-3
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-4
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-5
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-6
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-7
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-8
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-9
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-10
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-11
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-12
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-13
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-14
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-15
< / > Desenvolvimento de Aplicativos para Dispositivos Móveis 12
12-16
EXERCÍCIOS PROPOSTOS
12-17
3) Considere o código abaixo e escolha a alternativa correta
EX ER C ÍC IO S PR O PO STO S
1| fun pegaTodosItensDaLista(context: Con-
text, callBack: () -> Unit) {
2| executor.execute {
3| val dataBase = ItemDataBase.pegaInstancia
(context)
4| listaItens = dataBase?.itemDao()?.pega
TodosItens()!!
5| handler.post{
6| callBack()
7| }
8| }
9| }
12-18
5| handler.post {
6| callBack()
EX ER C ÍC IO S PR O PO STO S
7| }
8| }
9| }
12-19
( ) -b) Existe apenas um erro neste código, pois na linha 3 devemos
usar o operador ? Para acessar o atributo itemDao e nova-
EX ER C ÍC IO S PR O PO STO S
mente para acessar o método deleteTodos.
( ) -c) O código possui apenas um erro, pois não foi usado o método
post do objeto handler não foi usado para retornar o callback
na mesma thread que cuida dos elementos da interface gráfica.
( ) -d) Existem dois erros neste código, um deles é o uso do ope-
rador ? na linha 4 e o segundo é o uso do método post do
objeto handler para chamar o método de callback na thread
dos elementos gráficos.
( ) -e) Existe apenas um erro neste código que é a chamada do mé-
todo clear do objeto listaItens.
12-20
7) Considere o código abaixo e escolha a alternativa correta:
EX ER C ÍC IO S PR O PO STO S
1| private fun defineBotaoSalvar() {
2| val botaoSalvar = findViewById<Button>
(R.id.salvarButton)
3| botaoSalvar.setOnClickListener {
4| val item = criaItemLista()
5| L istaDeCompras.adicionarItemNaLis-
ta(item, this){
6| finish()
7| }
8| }
9| }
8) Qual foi a classe que não precisou ter nenhum método modificado após a
inclusão da funcionalidade de persistência ?
( ) -a) ListaDeCompras
( ) -b) MainActivity
( ) -c) VisualizaItemActivity
( ) -d) LinhaLinhaLista
( ) -e) AdicionaItemActivity
12-21
9) Qual camada do modelo MVC sofreu mais modificações depois da imple-
EX ER C ÍC IO S PR O PO STO S
mentação da funcionalidade de persistência?
12-22
REFERÊNCIAS
13-1
" GABARITO
Capítulo 1:
1) (d) 6) (c)
2) (d) 7) (d)
3) (c) 8) (b)
4) (a) 9) (a)
5) (c) 10) (c)
Capítulo 2:
1) (d) 6) (c)
2) (e) 7) (e)
3) (b) 8) (b)
4) (a) 9) (c)
5) (c) 10) (d)
Capítulo 3:
1) (d) 6) (b)
2) (a) 7) (d)
3) (d) 8) (e)
4) (b) 9) (b)
5) (c) 10) (a)
14-1
Capítulo 4:
G ABAR I TO
1) (d) 6) (c)
2) (e) 7) (d)
3) (d) 8) (b)
4) (c) 9) (b)
5) (e) 10) (a)
Capítulo 5:
1) (c) 6) (b)
2) (a) 7) (a)
3) (c) 8) (a)
4) (a) 9) (b)
5) (c) 10) (c)
Capítulo 6:
1) (e) 6) (e)
2) (a) 7) (e)
3) (b) 8) (d)
4) (c) 9) (d)
5) (b) 10) (e)
Capítulo 7:
1) (c) 6) (d)
2) (b) 7) (d)
3) (c) 8) (b)
4) (b) 9) (c)
5) (c) 10) (e)
14-2
Capítulo 8:
G ABAR I TO
1) (c) 6) (c)
2) (e) 7) (d)
3) (b) 8) (d)
4) (b) 9) (d)
5) (d) 10) (e)
Capítulo 9:
1) (c) 6) (c)
2) (c) 7) (b)
3) (d) 8) (a)
4) (b) 9) (e)
5) (a) 10) (a)
Capítulo 10:
1) (b) 6) (e)
2) (a) 7) (a)
3) (c) 8) (c)
4) (d) 9) (b)
5) (d) 10) (c)
Capítulo 11:
1) (b) 6) (d)
2) (d) 7) (c)
3) (d) 8) (d)
4) (a) 9) (b)
5) (d) 10) (c)
14-3
Capítulo 12:
G ABAR I TO
1) (c) 6) (c)
2) (b) 7) (b)
3) (e) 8) (d)
4) (d) 9) (c)
5) (d) 10) (b)
14-4
1º EDIÇÃO - 2021
Editora
SÃO PAULO/ SP