Aula 02 · Semana 3 · Terça, 22 de setembro de 2026 · 08:30 às 10:30
Arranque: continuação do setup, com o emulador a instalar-se em segundo plano. Teoria: o que acontece entre o código e os pixels do ecrã, e porque o hot reload é possível. Prática: Dart no DartPad, sem instalação, e o primeiro repositório no GitHub.
Ontem ficou a instalação base. Hoje começa o que demora: o emulador. Quem tem telemóvel Android com cabo pode saltar este passo.


flutter --version responde num terminal novo.flutter doctor --android-licenses).flutter doctor: ✓ em Flutter, Android toolchain e Android Studio.O que faltar fica para casa, com o guia; a prática de hoje corre no browser e não depende de nada disto.
| Camada | Escrita em | O que faz |
|---|---|---|
| Framework | Dart | O que se usa no dia a dia: widgets (Material, Cupertino), layout, animações, gestos, tema. Código Dart aberto, dentro do SDK. |
| Engine | C++ | Desenha (Impeller), executa o Dart (Dart VM em desenvolvimento, código AOT em release), trata de texto, imagens, e fala com a plataforma. |
| Embedder | Kotlin/Java, Swift/Objective-C, C++ | Específico de cada sistema: cria a janela ou a Activity, entrega eventos de toque, ciclo de vida, acessibilidade, e canais para código nativo. |
Um widget é um objeto Dart imutável que descreve um pedaço de interface. Compõem-se uns dentro dos outros numa árvore.
import 'package:flutter/material.dart';
void main() => runApp(const TempoApp());
class TempoApp extends StatelessWidget {
const TempoApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Tempo Açores')),
body: const Center(child: Text('Ponta Delgada · 21 °C')),
),
);
}
}
build não desenha nadaDevolve a descrição do que deve existir. O framework compara a descrição nova com a anterior e só mexe no que mudou. Chamar build muitas vezes é normal e barato; é assim que o Flutter foi desenhado.
Para os testes: um widget é imutável; o que muda é o estado, e o estado vive noutro sítio.
build é uma lista de compras, não a ida às compras. Escrever a lista muitas vezes é barato; o framework é quem vai à loja, e só compra o que mudou em relação à lista anterior.build. O estado mantém-se: um formulário meio preenchido no terceiro ecrã continua lá. Menos de um segundo.main, uma variável global, ou o tipo de um estado.pubspec.yaml, código nativo, ou recursos. Voltar a correr flutter run.null. Uma família inteira de crashes desaparece antes de a app correr.async/await na linguagem, isolates para trabalho pesado sem bloquear o ecrã.Abrir dartpad.dev. Hoje não é preciso o Flutter: só Dart, no browser.
Constrói-se, passo a passo, o modelo de dados que a app do projeto vai usar. Seis blocos, cada um com um exercício curto no fim.
void main() {
var cidade = 'Ponta Delgada'; // tipo inferido: String
int dia = 21;
double temperatura = 21.5;
bool chove = false;
final ilha = 'São Miguel'; // atribuído uma vez, em runtime
const maxDias = 5; // constante em tempo de compilação
print('$cidade, $ilha: $temperatura °C, chuva: $chove');
print('Dia ${dia + 1} de $maxDias');
}
var infere o tipo e fixa-o. cidade = 3; é erro de compilação.final para valores que não mudam depois de atribuídos. É a escolha por defeito; var só quando é preciso reatribuir.const é para constantes conhecidas em compilação. Em Flutter, const aparece em muitos widgets, por uma razão de desempenho.$nome ou ${expressão}.main, acrescentar double tMin = 17.0; e double tMax = 23.0;, calcular a amplitude (tMax - tMin) e imprimir, com interpolação e uma casa decimal (toStringAsFixed(1)), exatamente: Amplitude: 6.0 °C.void main() {
String nome = 'Horta';
String? alcunha; // pode ser null; tem de ser declarado com ?
// nome = null; // erro de compilação
print(alcunha ?? 'sem alcunha'); // ?? dá um valor por defeito
print(alcunha?.length); // ?. só chama se não for null → null
alcunha = 'Cidade do Mar';
print(alcunha.length); // o compilador já sabe que não é null aqui
late String descricao; // prometo inicializar antes de usar
descricao = '$nome, $alcunha';
print(descricao);
}
null. String? é um tipo diferente de String.??, ?. e ??= são os operadores do dia a dia.! força ("confio que não é null") e é uma origem frequente de crashes. Convém evitá-lo.main, acrescentar int? humidade; e uma linha que imprime Humidade: n/d quando é null e Humidade: 80% quando tem valor, sem usar ! (dica: humidade == null ? 'n/d' : '$humidade%', ou ??). Testar as duas situações: uma vez antes e outra depois de humidade = 80;.double celsiusParaFahrenheit(double c) => c * 9 / 5 + 32;
String descreve(String cidade, {required double tMax, double? tMin, bool chuva = false}) {
final min = tMin == null ? '' : ', mín $tMin';
return '$cidade: máx $tMax$min${chuva ? ', chuva' : ''}';
}
void main() {
print(celsiusParaFahrenheit(21));
print(descreve('Angra', tMax: 24));
print(descreve('Horta', tMax: 22, tMin: 17, chuva: true));
final formatar = (double t) => '${t.round()} °C'; // função como valor
print(formatar(21.6));
}
{required double tMax, bool chuva = false}. Em Flutter quase tudo usa parâmetros nomeados.required obriga; um valor por defeito torna opcional; ? permite null.=> para funções de uma expressão. Funções são valores: podem guardar-se e passar-se.String classifica({required double t}) que devolve 'frio' abaixo de 15, 'ameno' até 25 e 'quente' acima. Depois usá-la dentro de descreve, para descreve('Horta', tMax: 22, tMin: 17, chuva: true) passar a devolver Horta: máx 22.0, mín 17.0, chuva (ameno).flutter doctor com ✓ em Flutter, Android toolchain e Android Studio; emulador criado (ou telemóvel com depuração USB). Confirma-se amanhã na aula.