Alura > Cursos de Mobile > Cursos de Android > Conteúdos de Android > Primeiras aulas do curso Jetpack Compose: armazenamento de dados internos

Jetpack Compose: armazenamento de dados internos

Tipos de armazenamento - Apresentação

Olá! Meu nome é Júnior, e eu serei seu instrutor nesse curso de Jetpack Compose: Armazenamento de dados internos. Eu sou um homem de pele clara, cabelos loiros escuros compridos, que vem até a altura dos ombros, mais ou menos, olhos castanhos e utilizo um óculos de armação preta com as lentes bem grandes. Geralmente, nos vídeos, eu estou com uma camiseta da cor preta.

Esse é um curso que vai ensinar para você uma das técnicas mais importantes, e eu diria até que mais divertidas, da criação de aplicativos Android, que é o armazenamento de dados. O que significa que você vai poder criar aplicações, que quando você insere uma informação, fecha o aplicativo e volta a abri-lo, aquela informação ainda está lá. E a partir disso, você pode criar muitas outras coisas, nós vamos ver algumas delas.

Porém, antes de mais nada, como este é um curso um pouco mais avançado, para você se sentir confortável com todo o conteúdo que vamos ver, eu vou recomendar que você tenha antes alguns conhecimentos, alguns pré-requisitos.

Esses pré-requisitos são justamente saber primeiramente lidar com Jetpack Compose, principalmente com a criação e gerenciamento de formulários, receber informações de diferentes tipos, saber armazená-las e realmente lidar com elas, com os estados do Compose.

Também vamos utilizar bastante viewmodel e stakeholders, principalmente ligado à questão de UI States, para poder separar a lógica, para poder atualizar a nossa interface, e também vamos utilizar a API Navigation, para poder realizar a navegação entre as telas do nosso aplicativo.

Também vamos fazer o uso de mais três tecnologias, que são o Coroutines e o Flow, para operação assíncronas, e deixar nossa interface mais reativa, e o Hilt para injeção de dependências.

Porém, essas são tecnologias que quando formos fazer o uso, eu vou mostrar brevemente para o que elas servem, explicar principalmente como você pode utilizá-las dentro da nossa implementação, mas caso você queira se aprofundar ainda mais, ou não tenha as visto dentro do Compose, quer realmente entender como elas funcionam, eu vou oferecer alguns materiais extras para você poder consultar e se aprofundar ainda mais, caso desejar.

O projeto que vamos utilizar ao longo desse curso, é o aplicativo HelloApp, uma espécie de agenda de contatos. O HelloApp, quando clicamos para poder abrir, vai exibir uma tela de loading, que já está lidando com armazenamento de dados internos, para decidir qual tela ele vai nos mostrar.

A primeira tela que vamos ter contato nesse momento é a tela de lista de contatos. Ela permite observarmos quais contatos foram inseridos, clicar para poder visualizar as informações, e possuímos um float action button, um botão, que quando clicado, permite podermos criar um novo contato inserindo o link de uma imagem de perfil, um nome, também um sobrenome, eu vou até colocar um pouco diferente, e também um telefone, claro.

Opcionalmente, também podemos adicionar uma data de aniversário para este contato. Podemos salvá-lo, ele vai ser listado para nós, e ao fechar o aplicativo e voltar a abri-lo, a informação que acabamos de inserir ainda se mantém. Então, eu posso clicar para poder visualizá-la.

Vamos aprender também a como editar uma informação, então eu tenho um botão que é um lápis, quando eu clico eu vou para o mesmo formulário, posso editar a informação inserida e ela vai ser atualizada para nós. Também vou poder excluir essa informação caso eu não deseje mais tê-la.

Para poder fazer isso, vamos ver algumas técnicas, alguns meios de armazenamento e vamos utilizar um outro meio de armazenamento para implementar um outro fluxo do nosso aplicativo, que podemos acessar clicar no botão de deslogar o usuário, que fica no canto superior direito da tela.

Esse vai nos dar acesso ao fluxo de login, que vamos poder criar uma conta utilizando um método diferente do que utilizamos para poder criar um contato, a partir desse ponto vamos implementar também uma pequena tela de login, que inclusive possui um mecanismo de autenticação, que vamos implementar baseado também nos dados internos do armazenados.

E por fim, embora seja um pouco difícil de mostrar, vamos utilizar um outro meio de armazenamento para poder decidir qual tela será exibida. Então, nesse momento o aplicativo se lembra que não estamos mais logados, aquela tela de loading verificou isso para nós, e nos mostrou a tela de login, não mais o fluxo de lista de contatos.

Dito tudo isso, vamos ver algumas outras técnicas, algumas outras peculiaridades, eu espero que você esteja empolgado para poder começar com esse conteúdo. Em qualquer momento do curso sempre é bom você dar uma olhada nos links das atividades, caso você tenha alguma dúvida ou queira se aprofundar em alguma coisa a mais, e também vale sempre a pena dar uma conferida no nosso fórum e no nosso canal do Discord. Então, se você já estiver pronto, já estiver pronta, vamos lá.

Tipos de armazenamento - Conhecendo o projeto

Como o foco do nosso curso é justamente falar sobre o armazenamento de dados internos, eu já vou disponibilizar uma versão inicial do nosso aplicativo, que possui toda a parte de implementação de interface, de navegação e outros componentes já vistos nos cursos anteriores, já prontos, já feitos, apenas para irmos de fato para o que interessa.

Mas antes, eu acho que é importante reservarmos um primeiro momento para conhecer o nosso aplicativo, o nosso projeto inicial, entender como ele está estruturado para ficar um pouco mais fácil de prosseguirmos com o curso.

Então, eu já tenho o nosso aplicativo rodando, não se preocupe, eu vou disponibilizar o download dessa versão inicial para você poder baixar, instalar, e abrir no seu Android Studio. Esse aplicativo, por enquanto, quando abrimos, mostra uma tela inicial que deveria listar os contatos inseridos, mas não somos capazes de salvar nenhum contato por enquanto.

Mas podemos ir no botão de adicionar e inserir um nome, inserir um sobrenome, inserir um telefone, e por mais que não seja obrigatório, clicar também em “Aniversário” e inserir uma data de aniversário.

Eu ainda posso adicionar uma imagem, que não é obrigatório, você pode não cadastrar uma imagem, mas colocando o link, deve ser carregado, e agora clicando em “Salvar”, o nosso aplicativo ainda não salva o contato, nem mesmo se eu sair, fechar e voltar ele ainda não salva, vamos trabalhar nisso a seguir.

A estrutura do projeto dentro do Android Studio está dividida da seguinte maneira: temos a nossa pasta “Data”, dentro dela temos o nosso “Contato”, que é o modelo principal, que vai conter os nossos campos de nome, sobrenome, telefone, aniversário. Nós temos alguns tipos variados, vamos observar com mais calma em um certo momento. Nós temos a pasta “extensions”, que são alguns arquivos que eu acabei criando para poder facilitar o trabalho.

Por exemplo, para mostrar uma mensagem eu tenho que mostrar a mensagem, que facilita a exibição de um toast. Eu tenho um “DataExtensions.kt” e também um “StringExtensions.kt”, que servem para podermos formatar uma data, uma informação e mostrá-la de uma maneira mais bonita, é um código bem simples, se você quiser dar uma olhada, fique à vontade.

Dentro do diretório “navigation”, eu vou ter alguns arquivos que são responsáveis por mostrar as nossas telas, na verdade, por guiar as nossas telas, para mostrar utilizamos os composables, mas vamos com calma.

Eu tenho no “DetalhesContato” basicamente a estrutura que eu vou encontrar em outros arquivos também nesse diretório que é o seguinte: Eu tenho uma extension de NavGraphBuilder, e eu tenho a rota que nos traz para ele, temos alguns argumentos, faço o uso de um ViewModel, possui um uiState, e coletamos isso para depois passarmos para o nosso composable.

Uma diferença importante nesse primeiro momento, é que estamos utilizando o Hilt nesse projeto, então quando eu começo a utilizar um ViewModel, eu faço isso através do hiltViewModel, e não mais apenas de um ViewModel como antes.

Nesse primeiro momento, isso não interfere em nada no nosso código, é bem semelhante ao que você já viu nos cursos anteriores. Quando tivermos que mexer com Hilt, e então isso vai trazer algumas vantagens para nós, eu comento um pouco melhor, mas saibam que o uso é praticamente igual ao que você já viu antes.

Então, eu tenho o uso do nosso ViewModel, que acaba trazendo para nós um state, e que passamos para o nosso composable. Cada um desses gráficos de navegação de “Navigation” vai possuir uma estrutura semelhante, inclusive, você pode acessá-lo, dar um “Ctrl + B” no composable específico e visualizar a estrutura, temos alguns eventos de clique, passamos o nosso state, modifier, podemos observar como ele foi construído, e ao final temos o nosso arquivo de preview.

Inclusive, esses arquivos vão possuir um preview, então, clicando em “Split”, conseguimos visualizar a tela de informações. Essa é a única tela, por enquanto, que já está no fluxo do nosso aplicativo, mas que não conseguimos visualizar, porque ela só aparece quando clicamos em um contato, e não conseguimos inserir um contato para clicar ainda, mas logo mais vamos ser capazes.

Então, podemos visualizar o preview de detalhes, posso visualizar também o nosso preview de formulário, dando um “Ctrl + B”, então eu consigo visualizar a estrutura, clicar também no “Split” e ele vai carregar.

Nós temos o nosso formulário, bem semelhante ao que já vimos, é a mesma tela que vimos agora à pouco. E a estrutura que nós temos dentro dessa tela que é o “FormularioContatoNavigation”, é semelhante também a anterior.

Fechando, eu vou abrir o nosso “HomeGraphNavigation”, que é o nosso formulário principal, que é a nossa navegação principal, então temos uma pequena diferença, que temos um startDestination dentro dele, e também temos a nossa rota indicando que para poder ser acessado, é esse destino que deve ser seguido, route = DestinoHelloApp.HomeGraph.rota.

Dentro dele, temos o nosso ListaContatosTela. Então, vou dar um “Ctrl + B” para poder entrar nele, e temos uma mudança. Eu vou clicar em “Split” para ele carregar o nosso preview, e enquanto isso, eu vou deslizar para o final do arquivo enquanto carregamos o nosso preview.

Então, ele já carregou o preview ao mesmo tempo, vou dar um zoom. E pode perceber que embora essa tela seja a mesma que vimos anteriormente no aplicativo, eu tenho já os nossos contatos aparecendo. Isso acontece porque fazemos uso de um recurso do preview, que permite que eu possa passar alguns parâmetros, visualizar a nossa tela com mais detalhes, e o que eu passei foi um contatosExemplo.

Dando um “Ctrl + B” nesse arquivo, ele está reservado em um diretório que eu já mostro, mas vamos ter alguns contatos já inseridos, com nome, sobrenome, telefone, algumas outras informações que servem para termos uma preview de como seria o nosso app, por mais que ainda não sejamos capazes de fazer com que ele fique daquela maneira quando rodamos, quando o aplicativo está em execução.

Esse arquivo também vai ser bem útil para nós, quando começarmos a fazer os testes de inserção. Então, para não precisar ficar digitando toda hora alguns dados, eu posso pegar o arquivo e utilizar um ou mais desses contatos já prontos para poder agilizar o nosso trabalho.

Fechando esse arquivo, eu vou abrir o nosso projeto novamente no canto, eu vou ter outros dois arquivos que não vamos focar tanto nesse momento, mas saibam que existe uma navegação para a nossa tela de login e também para algo chamado SplashScreen, que vamos observar ao final do curso.

Dentro do nosso diretório “SampleData” está a nossa lista de contatos, que são exemplos de dados, e dentro do nosso diretório “ui”, temos os nossos componentes do *composable. Então, por exemplo, eu tenho um arquivo que vai permitir que eu reutilize o AsyncImage, que é o componente de imagem. Então, eu utilizo em vários lugares do nosso projeto, eu separei, e quando quero utilizá-lo, eu apenas passo alguns parâmetros diferentes e reaproveito essa estrutura.

Eu tenho um arquivo de “Dialog”, que vai servir para mostrar aquelas caixas. Ele pega a nossa data de aniversário e também pega o link da nossa imagem de perfil. São implementações bem simples, que você pode olhar com mais calma, caso queira.

Eu coloquei dentro dos nossos diretórios mais específicos, por exemplo, o nosso composable de detalhes, que acabamos de visualizar, uma estrutura que se repete bastante é que eu armazenei o nosso composable, o UiState e o ViewModel no mesmo diretório, então vamos ver em “detalhes”, em “form” e em “home”. Em “home” temos uma diferença, que eu tenho o ListaContatosActivity.

O nosso ListaContatosActivity vai ser responsável por guiar todo o fluxo do nosso app, ela é a única activity nesse projeto, e fazemos a navegação entre as telas, utilizando o HelloAppNavHost, que é outro arquivo que eu já mostro aonde está, mas que dando um “Ctrl + B”, eu consigo ver o fluxo principal.

Então, eu tenho o nosso “home”, que vai mostrar a nossa lista de contatos que vimos anteriormente, o nosso formulário e nosso “detalhes”, são essas telas que temos inicialmente dentro do aplicativo.

Ao final, eu vou ter algumas extensões de NavHostController para poder facilitar algumas rotas que são bastante utilizadas no restante do projeto, não é nada muito especial, caso você queira também dar uma olhada com um pouco mais de detalhe, fique à vontade.

Fechando esses dois arquivos, eu ainda vou ter as duas telas que eu falei que existem e que não vamos observar com tanta calma nesse primeiro momento, e vamos ter o nosso arquivo “HelloAppNavHost”, que está separado e que acabamos de ver também.

Dentro da nossa pasta “útil”, eu tenho um arquivo de constantes, que vai ser novamente útil para algumas navegações que fazemos nosso projeto, algumas formatações também, não é algo que requeira muito detalhe, e eu vou ter também com o nosso “DestinosHelloApp”, que vai conter as rotas que vão permitir a navegação ocorrer dentro do aplicativo.

Então, eu tenho as principais rotas, e também tenho algumas que têm alguns detalhes a mais, como por exemplo alguns argumentos, algumas configurações já feitas, que são um pouco mais complexas para ficar dentro do nosso objeto principal.

Basicamente, esse é o nosso projeto, estamos prontos para poder começar o curso, então vamos lá.

Tipos de armazenamento - Tipos de armazenamento

Como nós vimos anteriormente, por enquanto nosso aplicativo não é capaz de salvar nenhuma informação internamente. Nós precisamos achar uma solução para contornar isso.

Existe uma página oficial da documentação do Android que fala sobre a visão geral do armazenamento de dados e arquivos. Dentro dessa página da documentação descrevem nesse início quatro tipos de armazenamento, e eu vou comentar sobre os quatro, falar sobre as diferenças e observar qual melhor vai nos atender neste primeiro momento.

Então, primeiro eles falam sobre “armazenamento específico”, que geralmente é para dados mais específicos dos aplicativos, que inclusive outros apps não podem acessar, e trata realmente de informações de segurança em diretórios dedicados, são informações que vão ficar bem mas próximas de onde o nosso aplicativo está instalado, o que geralmente são informações mais sensíveis, mais pequenas.

Dentro do “armazenamento compartilhado”, começamos a falar do escopo de mídias. Então, caso eu queira salvar uma imagem, um vídeo, ou mesmo um documento, quem sabe até um arquivo de texto, em teoria eu poderia utilizar o armazenamento compartilhado para salvar algum documento que tivesse as informações do contato, quando necessário ir recuperar e editar, excluir. Mas vamos dar uma olhada nas outras opções também.

Temos o “Preferências”, que serve para armazenar dados particulares e primitivos em chave-valor. O armazenamento chave-valor vamos ver um pouco mais para frente também, mas geralmente “Preferências” é utilizado para salvar informações mais simples, e também informações pequenas.

Como estamos falando de um caso do nosso app, em que eu posso salvar um contato que já possui várias informações e que eu vou poder salvar 10, 100, às vezes mil, quem sabe mais contatos, e isso não é ideal para nós no momento.

Sobra a última opção, que é o “banco de dados”, que permite armazenar dados em um banco particular, e eles já recomendam utilizar a biblioteca Room. Vamos comentar um pouco mais sobre o Room daqui a pouco. Mas antes, o banco de dados é uma solução que vai permitir salvar dados estruturados.

Um dado estruturado é um dado que podemos organizar em uma estrutura de tabela, por exemplo, e com esse dado organizado, com esse dado estruturado, eu consigo localizar uma informação mais fácil, fazer uma consulta, fazer uma edição. Realmente ficar muito melhor eu trabalhar com um dado estruturado, do que um dado não estruturado, um dado bagunçado, por assim dizer.

E como eles recomendam utilizar o banco de dados, é importante sabermos que por padrão não só o Android, como vários aparelhos celulares, grande parte dos computadores já vem com o banco de dados SQLite instalado.

E o SQLite é uma pequena variação do banco SQL, ele é um banco pequeno, muito rápido, que já vem instalado, como mencionamos, em vários aparelhos, o que faz com que ele seja muito utilizado. Ele possui algumas outras vantagens, e caso você já tenha trabalhado com um banco de dados como o Postgres SQL, o MySQL, ou outro semelhante, você pode ter uma certa facilidade para trabalhar com SQLite.

E podemos pensar que o SQLite já está no meu aparelho Android, ele não quer nenhuma instalação, ele já está lá por padrão, seria uma ótima alternativa para começarmos a armazenar os nossos contatos. Porém, na própria página da documentação do Android, que ensina como utilizar o SQLite, tem alguns códigos, inclusive caso você queira entender como funciona, uma das primeiras coisas que temos é um aviso.

O aviso é o seguinte: “Cuidado: embora essas APIs sejam poderosas, elas são de um nível bastante baixo e exigem muito tempo e esforço para serem usadas”. E tem dois problemas principais que são mencionados, o primeiro é que não existe verificação em tempo de compilação de consultas SQL brutas.

O que isso quer dizer? Quer dizer que enquanto estamos escrevendo um código com essa API SQLite no Android, se cometermos um erro, não vamos ver avisados que esse erro vai ser cometido, e só quando rodarmos o aplicativo e ele quebrar, que vamos descobrir.

Também é dito que é necessário muito código boilerplate para converter consultas SQL em objetos de dados. Isso quer dizer que precisamos de muito código que é repetitivo, e que precisa ser inserido em muitos lugares, às vezes com pouca modificação ou com nenhuma, e isso faz com que o desenvolvimento fique mais lento, e novamente fique mais suscetível a erros.

Por isso é altamente recomendável utilizar a biblioteca de persistências Room. Inclusive, tem um link que podemos clicar e ir para a documentação do Room. Vamos comentar um pouco melhor sobre o que ele é, como ele funciona a seguir, mas saibam por enquanto que ele já faz parte do pacote Android Jetpack, que faz parte de um conjunto de ferramentas para acelerar o desenvolvimento de aplicações Android.

Então, agora que já sabemos o que precisamos, está na hora de conhecer um pouco melhor dessa ferramenta Room.

Sobre o curso Jetpack Compose: armazenamento de dados internos

O curso Jetpack Compose: armazenamento de dados internos possui 163 minutos de vídeos, em um total de 62 atividades. Gostou? Conheça nossos outros cursos de Android em Mobile, ou leia nossos artigos de Mobile.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Android acessando integralmente esse e outros cursos, comece hoje!

Plus

De
R$ 1.800
12X
R$109
à vista R$1.308
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

Matricule-se

Pro

De
R$ 2.400
12X
R$149
à vista R$1.788
  • Acesso a TODOS os cursos da Alura

    Mais de 1500 cursos completamente atualizados, com novos lançamentos todas as semanas, emProgramação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

  • Luri powered by ChatGPT

    Luri é nossa inteligência artificial que tira dúvidas, dá exemplos práticos e ajuda a mergulhar ainda mais durante as aulas. Você pode conversar com Luri até 100 mensagens por semana.

  • Alura Língua (incluindo curso Inglês para Devs)

    Estude a língua inglesa com um curso 100% focado em tecnologia e expanda seus horizontes profissionais.

Matricule-se
Conheça os Planos para Empresas

Acesso completo
durante 1 ano

Estude 24h/dia
onde e quando quiser

Novos cursos
todas as semanas