Introdução

Imagine que você está no metrô, esperando o café ficar pronto, ou deitado no sofá antes de dormir. O que você faz? Muito provavelmente, pega o celular. Essa cena, repetida bilhões de vezes por dia em todo o planeta, revela algo profundo: o smartphone deixou de ser um acessório e tornou-se uma extensão do ser humano contemporâneo. E por trás de cada aplicativo que captura atenção, resolve um problema ou conecta pessoas, há um desenvolvedor que aprendeu a construir experiências para a tela que cabe na palma da mão. Este material existe para transformar você nesse desenvolvedor.


O Mundo que Cabe no Bolso

Para entender por que o desenvolvimento mobile é tão relevante, vale a pena dar um passo atrás e observar os números. Em 2024, o planeta contava com mais de 6,8 bilhões de usuários de smartphones, o que equivale a mais de 85% da população mundial com acesso a dispositivos móveis. A Google Play Store e a Apple App Store, juntas, hospedam mais de 5 milhões de aplicativos. Mais impressionante ainda: o tempo médio que um adulto passa olhando para a tela do celular supera quatro horas diárias, um número que continua crescendo ano após ano.

Esse cenário não é apenas estatístico; ele é econômico. O mercado global de aplicativos móveis movimentou mais de 430 bilhões de dólares em 2022 e as projeções indicam que esse valor deve dobrar até 2030. O desenvolvedor mobile, portanto, não aprende uma habilidade qualquer: ele aprende uma das habilidades mais valorizadas e com maior demanda no mercado de trabalho em tecnologia.

Por que isso importa para você, estudante de Ciência da Computação?

Você chegou até o quinto semestre percorrendo um caminho que passou por lógica de programação, estruturas de dados, orientação a objetos, banco de dados e engenharia de software. Cada um desses conhecimentos foi construído sobre o anterior, e agora todos eles convergem para um ponto: construir aplicações reais que as pessoas usam de verdade. O desenvolvimento mobile é, talvez, o campo onde essa convergência se torna mais visível e mais imediata. Quando um usuário abre um aplicativo que você desenvolveu e consegue resolver um problema, o resultado do seu trabalho é palpável de uma forma que poucas áreas da computação proporcionam.

Além disso, o desenvolvimento mobile moderno não vive isolado. Um aplicativo completo envolve interfaces sofisticadas, comunicação com servidores em nuvem, persistência de dados, autenticação de usuários, notificações em tempo real e até mesmo acesso a sensores físicos do dispositivo, como câmera, GPS e acelerômetro. Estudar sistemas móveis significa, portanto, estudar um ecossistema tecnológico completo, que integra frontend, backend, segurança e infraestrutura em um único produto.


De Onde Viemos: A Evolução do Desenvolvimento Mobile

Para valorizar o que temos hoje, é importante entender o que havia antes. A história do desenvolvimento mobile pode ser contada em três grandes eras, e cada uma delas deixou lições que moldaram as ferramentas atuais.

%%| label: evolucao-mobile
%%| fig-cap: Evolução do Desenvolvimento Mobile
%%| fig-width: 11
timeline
    title Evolução do Desenvolvimento Mobile
    2007 : iPhone lançado pela Apple
         : Início da era dos smartphones modernos
    2008 : App Store e Google Play abertas ao público
         : Corrida pelo desenvolvimento nativo
    2012 : Ionic e PhoneGap ganham popularidade
         : Primeira onda de desenvolvimento híbrido
    2015 : React Native lançado pelo Facebook
         : Multiplataforma baseado em JavaScript
    2017 : Dart e Flutter apresentados pela Google
         : Nova abordagem com renderização própria
    2018 : Flutter 1.0 liberado para produção
         : Adoção acelerada pela indústria
    2021 : Flutter 2.0 — suporte web e desktop
         : Plataforma verdadeiramente multiplataforma
    2024 : Flutter consolidado como padrão de mercado
         : Milhares de apps publicados no mundo inteiro

A primeira era foi a do desenvolvimento nativo puro. Quando a Apple abriu a App Store em 2008, a única maneira de criar um aplicativo para iPhone era usando Objective-C (e, mais tarde, Swift) com as ferramentas da própria Apple. Para Android, o caminho era Java (e depois Kotlin) com o Android SDK do Google. Cada plataforma tinha seu próprio conjunto de bibliotecas, suas próprias convenções e seu próprio ciclo de vida. O resultado era aplicativos com desempenho excelente e acesso total aos recursos do dispositivo, mas o preço era alto: uma empresa que quisesse estar presente tanto no iOS quanto no Android precisava manter duas equipes separadas, dois repositórios distintos e dois processos independentes de desenvolvimento.

A segunda era foi a do desenvolvimento híbrido, impulsionado pelo desejo de escrever código uma única vez e executá-lo em múltiplas plataformas. Ferramentas como Apache Cordova, PhoneGap e depois Ionic propunham uma solução elegante: usar HTML, CSS e JavaScript para construir a interface do aplicativo, que seria então empacotada dentro de uma visualização web nativa (um WebView). O código era reutilizável, mas o desempenho sofria, pois a interface não era renderizada pelos componentes nativos de cada plataforma. A experiência do usuário costumava ser perceptivelmente inferior à de um app nativo, especialmente em animações e transições.

A terceira era é a dos frameworks multiplataforma modernos, e é aqui que o Flutter se insere. A grande inovação desta era foi rejeitar o WebView e ao mesmo tempo evitar a necessidade de código nativo por plataforma. O Flutter adota uma abordagem diferente: ele traz seu próprio motor de renderização gráfica (Skia, e mais recentemente Impeller) e desenha cada pixel da interface diretamente na tela, sem depender dos componentes nativos de cada sistema operacional. Isso elimina as inconsistências entre plataformas e garante desempenho comparável ao código nativo.


Flutter: A Tecnologia que Você vai Dominar

O Flutter é um framework de desenvolvimento de interface criado pela Google, com a linguagem Dart como base. A escolha do Flutter para esta disciplina não foi arbitrária; ela reflete uma análise cuidadosa do mercado de trabalho, das tendências tecnológicas e das características pedagógicas que tornam uma ferramenta adequada para o aprendizado.

Do ponto de vista arquitetural, o Flutter funciona de forma radicalmente diferente de outros frameworks. Em vez de traduzir componentes de interface para widgets nativos de cada plataforma (como faz o React Native), o Flutter compila o código Dart diretamente para código de máquina nativo e usa seu próprio motor de renderização para desenhar a interface. Isso significa que um botão no Flutter tem a mesma aparência no Android, no iOS, no Windows e na web, porque ele é literalmente desenhado pelo Flutter, não pelo sistema operacional.

%%| label: arquitetura-flutter
%%| fig-cap: Arquitetura Flutter
%%| fig-width: 11
flowchart TB
    subgraph Seu_Codigo["Seu Código Dart"]
        Widgets["Widgets da Interface"]
        Logica["Lógica de Negócio"]
        Estado["Gerenciamento de Estado"]
    end

    subgraph Flutter_Framework["Flutter Framework"]
        Material["Material / Cupertino<br/>(componentes de UI)"]
        Rendering["Motor de Renderização"]
        Foundation["Fundações e Utilitários"]
    end

    subgraph Motor["Motor Flutter (C++)"]
        Skia["Impeller / Skia<br/>(renderização gráfica)"]
        Dart_VM["Dart VM / AOT"]
        Platform_Channels["Platform Channels"]
    end

    subgraph Plataformas["Plataformas Suportadas"]
        Android["Android"]
        iOS["iOS"]
        Web["Web"]
        Desktop["Windows / Linux / macOS"]
    end

    Widgets --> Material
    Logica --> Foundation
    Estado --> Foundation
    Material --> Rendering
    Rendering --> Skia
    Dart_VM --> Android
    Dart_VM --> iOS
    Dart_VM --> Web
    Dart_VM --> Desktop
    Platform_Channels --> Android
    Platform_Channels --> iOS

    style Seu_Codigo fill:#cfe2ff,stroke:#0d6efd
    style Flutter_Framework fill:#d1ecf1,stroke:#17a2b8
    style Motor fill:#fff3cd,stroke:#ffc107
    style Plataformas fill:#d4edda,stroke:#28a745

A linguagem Dart, por sua vez, foi projetada para ser familiar para quem já conhece linguagens orientadas a objetos como Java, C# ou Python, mas traz características modernas que tornam o código mais seguro e expressivo. O sistema de tipos do Dart é fortemente tipado com null safety, o que significa que o compilador ajuda você a evitar um dos erros mais comuns em programação: tentar usar um valor que é nulo quando não deveria ser. Dart também suporta programação assíncrona de forma elegante com as palavras-chave async e await, o que é fundamental para aplicações mobile que fazem requisições a servidores e leem dados de sensores sem travar a interface do usuário.

Por que Flutter e não React Native?

Essa é uma pergunta legítima, e a resposta honesta é: ambos são boas opções profissionalmente. React Native tem uma base maior de desenvolvedores, especialmente entre quem já conhece JavaScript e o ecossistema React. No entanto, o Flutter oferece algumas vantagens que o tornam particularmente adequado para fins de aprendizagem e para um mercado que valoriza consistência e desempenho.

A primeira vantagem é a previsibilidade visual. Como o Flutter renderiza sua própria interface, o comportamento do aplicativo é idêntico em todas as plataformas, o que elimina uma classe inteira de bugs relacionados a diferenças entre sistemas operacionais. A segunda é o desempenho: a compilação ahead-of-time (AOT) do código Dart gera binários nativos que executam com fluidez comparável a código escrito diretamente em Kotlin ou Swift. A terceira é a documentação, que é extensa, bem organizada e constantemente atualizada pela Google. Finalmente, o crescimento da adoção do Flutter no mercado brasileiro e mundial torna essa habilidade cada vez mais valorizada no currículo de um desenvolvedor.


A Arquitetura Completa que Você vai Construir

Esta disciplina não se limita à interface do aplicativo. Um sistema mobile moderno é composto por camadas que vão muito além do que o usuário vê na tela. Ao longo do semestre, você terá contato com cada uma dessas camadas e aprenderá como elas se integram para formar um produto coeso.

%%| label: arquitetura-sistema
%%| fig-cap: Arquitetura do Sistema
%%| fig-width: 11
flowchart LR
    subgraph Dispositivo["Dispositivo do Usuário"]
        App["Aplicativo Flutter<br/>(Dart)"]
        Cache["Cache Local<br/>(SQLite / SharedPrefs)"]
        Sensores["Recursos Nativos<br/>(Câmera, GPS, Bio)"]
    end

    subgraph Internet["Camada de Rede"]
        HTTPS["HTTPS / REST"]
        FCM_Net["FCM Push"]
    end

    subgraph AWS["Amazon Web Services"]
        APIGW["API Gateway<br/>(REST API)"]
        Lambda["Lambda Functions<br/>(lógica de negócio)"]
        RDS["RDS PostgreSQL<br/>(banco de dados)"]
        SQS["SQS<br/>(filas de mensagens)"]
    end

    subgraph Google["Google Firebase"]
        FCM["Firebase Cloud<br/>Messaging (FCM)"]
    end

    subgraph Auth["Autenticação"]
        OAuth["OAuth 2.0 / JWT"]
    end

    App --> Cache
    App --> Sensores
    App -- HTTPS --> APIGW
    APIGW --> Lambda
    Lambda --> RDS
    Lambda --> SQS
    SQS --> FCM
    FCM -- FCM_Net --> App
    OAuth --> App
    OAuth --> APIGW

    style Dispositivo fill:#cfe2ff,stroke:#0d6efd
    style AWS fill:#fff3e0,stroke:#f57c00
    style Google fill:#fce4ec,stroke:#c2185b
    style Auth fill:#e2d9f3,stroke:#6f42c1

O aplicativo Flutter é o que o usuário vê e toca. Ele é responsável pela interface, pela navegação entre telas, pela validação de formulários, pelo gerenciamento do estado local e pela comunicação com o backend. Internamente, o aplicativo organiza seu comportamento usando o padrão Provider para gerenciamento de estado, go_router para navegação declarativa e http para chamadas à API.

O backend na AWS é o cérebro invisível da aplicação. O API Gateway recebe as requisições HTTP do aplicativo e as encaminha para funções Lambda, que são pequenos pedaços de código executados sob demanda na nuvem, sem necessidade de um servidor dedicado. Essas funções acessam o banco de dados PostgreSQL no RDS para ler e gravar dados, e podem publicar mensagens no SQS quando precisam disparar processamentos assíncronos, como enviar um e-mail de confirmação ou processar uma imagem.

O Firebase Cloud Messaging é o mecanismo pelo qual o servidor consegue enviar notificações para os dispositivos dos usuários, mesmo quando o aplicativo não está aberto. Quando algo relevante acontece no backend, uma mensagem é publicada no FCM, que a encaminha para o dispositivo correto.

A autenticação permeia toda essa arquitetura. O aplicativo usa OAuth 2.0 e tokens JWT para garantir que cada requisição ao backend seja feita por um usuário autenticado e autorizado. O armazenamento seguro de tokens no dispositivo é feito com o pacote flutter_secure_storage, que usa o sistema de armazenamento criptografado de cada plataforma.


A Linguagem Dart: Um Breve Encontro Antecipado

Antes de partir para os módulos do curso, vale a pena ter um primeiro contato com a linguagem que usaremos ao longo de todo o semestre. Dart não será difícil para você: se você já escreveu código em Java, C# ou Python, a sintaxe de Dart vai parecer familiar. A diferença está nos detalhes modernos que tornam Dart particularmente adequado para o Flutter.

Considere o exemplo a seguir, que representa um conceito que você encontrará no Módulo 02. Não se preocupe em entender tudo agora; o objetivo é apenas mostrar como Dart se parece.

// Dart usa o conceito de "null safety": o compilador garante que você
// não vai tentar usar uma variável que seja nula sem perceber.

// Uma classe simples representando um produto do nosso aplicativo.
class Produto {
  // O tipo 'String' aqui é "não-nulável": o nome SEMPRE terá um valor.
  final String nome;

  // O tipo 'double?' com a interrogação significa "pode ser nulo".
  // O preço pode não estar disponível ainda.
  final double? preco;

  // Construtor nomeado com parâmetros obrigatórios e opcionais.
  const Produto({
    required this.nome, // 'required' obriga quem chama a fornecer o nome
    this.preco,         // 'preco' é opcional — pode ser omitido
  });

  // Um método simples que retorna uma descrição do produto.
  String descricao() {
    final precoFormatado = preco != null
        ? 'R\$ ${preco!.toStringAsFixed(2)}'
        : 'Preço não disponível';
    return '$nome — $precoFormatado';
  }
}

// Funções assíncronas com async/await: a interface não trava
// enquanto esperamos dados do servidor.
Future<List<Produto>> buscarProdutos() async {
  // Aqui faríamos uma chamada HTTP, mas por ora simulamos com um atraso.
  await Future.delayed(const Duration(seconds: 1));

  return [
    const Produto(nome: 'Café Especial', preco: 18.90),
    const Produto(nome: 'Produto Temporário'), // sem preço definido
  ];
}
class Produto {
  final String nome;
  final double? preco;
  const Produto({required this.nome, this.preco});
  String get descricao =>
      '$nome — ${preco != null ? 'R\$ ${preco!.toStringAsFixed(2)}' : 'Preço não disponível'}';
}

Future<List<Produto>> buscarProdutos() async {
  await Future.delayed(const Duration(seconds: 1));
  return [
    const Produto(nome: 'Café Especial', preco: 18.90),
    const Produto(nome: 'Produto Temporário'),
  ];
}

Observe alguns pontos importantes nesse código. A declaração final indica que a variável não pode ser reatribuída após a inicialização, o que é uma boa prática para evitar erros. O símbolo ? após um tipo indica que aquela variável pode conter o valor nulo, e o compilador vai exigir que você trate essa possibilidade antes de usar o valor. O Future<T> é o tipo de retorno de funções assíncronas: ele representa uma promessa de que, em algum momento no futuro, haverá um valor do tipo T. E async/await tornam o código assíncrono quase tão legível quanto o código síncrono.


Como Este Material Está Organizado

Você terá em mãos um conjunto de documentos cuidadosamente elaborados para cada módulo da disciplina. Entender como esse material está organizado vai ajudá-lo a aproveitá-lo da melhor forma possível.

%%| label: organizacao-material
%%| fig-cap: Organização do Material
%%| fig-width: 11
flowchart TD
    CP["Conteúdo Programático<br/>(visão geral do semestre)"]
    PI["Projeto Integrador<br/>(o que você vai construir)"]

    CP --> M01["Material do Módulo<br/>(estude antes da aula)"]
    PI --> M01

    M01 --> EX["Exercícios<br/>(pratique o que aprendeu)"]
    M01 --> PP["Projeto do Professor<br/>(exemplo de implementação)"]

    style CP fill:#cfe2ff,stroke:#0d6efd
    style PI fill:#d4edda,stroke:#28a745
    style M01 fill:#d1ecf1,stroke:#17a2b8
    style PP fill:#e2d9f3,stroke:#6f42c1

O Conteúdo Programático é o documento que você deve ler primeiro. Ele apresenta todos os 15 módulos do curso e o que você aprenderá em cada um. É o seu mapa do semestre inteiro.

O Projeto Integrador descreve o produto de software que você e seu grupo irão desenvolver ao longo de todo o semestre. Leia-o com atenção logo no início, pois ele vai orientar todas as decisões técnicas que vocês tomarão nas semanas seguintes.

Para cada um dos 15 módulos, há um material didático que você deve estudar antes da aula presencial. Este é o coração do método de sala de aula invertida: você chega à aula com o conteúdo teórico já estudado, e o tempo em sala é usado para tirar dúvidas e desenvolver o projeto com a orientação do professor. Cada material didático é acompanhado de exercícios propostos para que você teste sua compreensão.

O Projeto do Professor é um exemplo concreto de implementação que o professor desenvolve em paralelo ao trabalho dos grupos. Ele serve como referência de qualidade e como ponto de partida para discussões sobre decisões de design e implementação.


A Dinâmica de Aprendizagem que Espera por Você

Esta disciplina foi construída sobre a convicção de que ninguém aprende a programar apenas lendo sobre programação. O conhecimento técnico se consolida na prática, no momento em que você tenta fazer algo, encontra um erro, investiga a causa, testa uma solução e vê o resultado. Por isso, a maior parte do tempo presencial é dedicada ao desenvolvimento do Projeto Integrador, com tutoria do professor disponível para orientar cada grupo.

A disciplina acontece em sessões de 4 aulas por módulo, assim organizadas: a primeira aula é dedicada à exposição teórica pelo professor, com espaço para perguntas e discussão dos conceitos estudados previamente. As três aulas seguintes são sessões de tutoria, nas quais cada grupo trabalha no Projeto Integrador enquanto o professor circula entre os grupos, oferece orientação e ajuda a desbloquear dificuldades. Não existem tarefas para fazer em casa além do estudo do material do próximo módulo.

Esse formato faz com que o aprendizado aconteça em ciclos curtos e frequentes: você estuda, pratica, recebe feedback, ajusta e avança. Ao final do décimo módulo, haverá uma entrega parcial do projeto, que serve como um ponto de verificação do progresso e como oportunidade de receber orientações para a segunda metade do semestre. A entrega final ocorre na semana seguinte ao décimo quinto módulo.


O que Você Será Capaz de Fazer ao Final do Semestre

Ao completar esta disciplina, você terá construído, de forma incremental e colaborativa, um aplicativo mobile completo. Mas além do produto final, você terá desenvolvido um conjunto de habilidades que são transferíveis para qualquer projeto futuro.

Competências desenvolvidas ao longo do semestre

Você será capaz de configurar e utilizar um ambiente de desenvolvimento mobile profissional, compreendendo o papel de cada ferramenta na cadeia de trabalho. Dominará a linguagem Dart com confiança, sabendo explorar seu sistema de tipos, programação assíncrona e orientação a objetos para escrever código limpo e manutenível. Construirá interfaces responsivas e atraentes com Flutter, aplicando os princípios de composição de widgets, gerenciamento de estado com Provider e navegação declarativa com go_router.

Saberá integrar o aplicativo com uma API REST, tratar respostas e erros de forma robusta e exibir dados ao usuário de maneira clara. Implementará persistência de dados tanto localmente, com SQLite e SharedPreferences, quanto remotamente, com um banco de dados PostgreSQL na AWS acessado via Lambda Functions. Configurará notificações push usando Firebase Cloud Messaging e saberá quando e como usá-las de forma que agreguem valor ao usuário. Implementará autenticação segura com OAuth 2.0 e armazenamento protegido de credenciais. Acessará recursos nativos do dispositivo, como câmera, GPS e autenticação biométrica. E, finalmente, preparará o aplicativo para publicação nas lojas, compreendendo o processo de assinatura, configuração e submissão.

Mais do que competências técnicas, você também desenvolvera a habilidade de trabalhar em equipe em um projeto de software real, gerenciar versões de código com Git e GitHub, documentar o progresso do desenvolvimento em um diário de projeto e apresentar um produto de software de forma clara e convincente.


Uma Palavra Sobre a Jornada que Começa

Aprender desenvolvimento mobile pode parecer, no início, uma tarefa monumental. São muitas ferramentas, muitos conceitos novos e muita coisa acontecendo ao mesmo tempo. É normal sentir isso. O que diferencia quem consegue avançar de quem desiste não é a ausência de dificuldades, mas a disposição de enfrentar uma dificuldade de cada vez.

Este material foi construído para ser seu companheiro de jornada. Cada módulo começa onde o anterior terminou, e nenhum conceito é introduzido sem que os pré-requisitos já tenham sido apresentados. Se em algum momento você sentir que algo não ficou claro, volte ao módulo anterior, releia o trecho relevante e tente o exercício correspondente. O material existe para ser usado, não apenas lido.

O Professor do Professor, neste caso, é o próprio processo de construir um aplicativo do zero até a publicação. Cada erro de compilação que você resolve, cada tela que você constrói, cada chamada de API que você integra com sucesso é um passo a mais na consolidação de um conhecimento que vai muito além desta disciplina.

Bem-vindo a Sistemas Móveis. O aplicativo que você vai construir começa aqui.