Gerenciamento de exceções e erros

Todas as exceções em Dart são exceções não verificadas: não é necessário declarar os tipos lançados nas funções e capturá-las não é obrigatório.

Existem duas categorias:

  • Exception:Erros previsíveis ligados à lógica de negócio (problemas de formato, parâmetros inválidos… Recomenda-se capturar e tratar esses casos).
  • Error:Erros fatais do programa (incompatibilidade de tipos, ponteiro nulo, métodos não implementados… Geralmente não são capturados).

Qualquer objeto não nulo pode ser lançado com a palavra-chave throw. Em projetos padronizados, apenas subclasses de Exception/Error são lançadas.

Qualquer exceção não capturada interrompe o isolate atual e causa o crash do aplicativo.

throw: lançar uma exceção

1. Lançar exceções nativas do sistema

void main() {
  // Exceção de formato
  throw FormatException("É necessário pelo menos um segmento de dados");
}
Code language: Dart (dart)
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
FormatException: Descrição do erro
#0      main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:3:3)
#1      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#2      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)

Esse código lança uma exceção nativa com uma mensagem personalizada que aparece na execução. Você pode se perguntar qual a utilidade disso, mas o lançamento de exceções é um mecanismo essencial no desenvolvimento. Por exemplo, no cadastro de usuários validamos os dados inseridos: se não estiverem em conformidade com as regras, lançamos imediatamente uma exceção para interromper o fluxo e alertar o usuário, evitando a inserção de dados inválidos e mantendo a integridade das informações.

2. Lançar qualquer objeto

Não recomendado para ambiente de produção

void main() {
  throw "Texto descritivo do erro!";
}Code language: Dart (dart)

Resultado da execução

D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
Texto descritivo do erro!
#0      main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:2:3)
#1      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#2      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)

3. Usar throw dentro de função de seta (throw é uma expressão)

class Point {}
void distanceTo(Point other) => throw UnimplementedError("Este método não foi implementado");

void main() {
  distanceTo(Point());
}
Code language: JavaScript (javascript)

III. Capturar exceções com try /on/catch

Diferenças de sintaxe

  • on TipoExceção:Apenas combina com exceções do tipo especificado, não é possível acessar o objeto da exceção.
  • catch(e):Captura todas as exceções, a variável e contém a instância da exceção.
  • catch(e, s):e = objeto da exceção, s = pilha de chamadas StackTrace.

1: Capturar um único tipo de exceção com on


// Criar uma classe de exceção personalizada que implementa Exception
class OutOfLlamasException implements Exception {}

// Função que lança a exceção personalizada acima
void breedMoreLlamas() {
  throw OutOfLlamasException();
}

void buyMoreLlamas() {
  print("A função buyMoreLlamas foi executada");
}

void main() {
  try {
    breedMoreLlamas(); // Chamar a função com código de risco
  } on OutOfLlamasException {
    buyMoreLlamas(); // Executado se OutOfLlamasException for capturada
  }
}Code language: Dart (dart)

Resultado da execução

D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
A função buyMoreLlamas foi executadaCode language: CSS (css)
try  {
    // Código suscetível a erros
} on ClasseExceção {
   // Lógica executada ao capturar o erro
}Code language: Dart (dart)

try on é apenas uma sintaxe dedicada à captura de exceções por tipo.

2: Captura hierárquica com múltiplos ramos

As correspondências mais precisas são processadas primeiro

class OutOfLlamasException implements Exception {}

void breedMoreLlamas() {
  throw FormatException("Erro de formato de dados");
}

void main() {
  try {
    breedMoreLlamas();
  }
  // 1. Correspondência exata com a exceção personalizada
  on OutOfLlamasException {
    print("Ocorreu o erro OutOfLlamasException");
  }
  // 2. Capturar todas as subclasses de Exception
  on Exception catch (e) {
    print("Exceção comum de negócio:$e");
  }
  // 3. Ramo de fallback para Error e qualquer outro objeto lançado
  catch (e) {
    print("Erro grave desconhecido:$e");
  }
}
Code language: Dart (dart)

Saída:Exceção comum de negócio:FormatException: Erro de formato de dados

É possível usar vários blocos on para capturar cada tipo de Exception separadamente, com um catch final como proteção universal.

3: Capturar exceção e imprimir pilha de chamadas StackTrace

void main() {
  try {
    int a = null;
    print(a + 1);
  } catch (e, stack) {
    print("Mensagem da exceção:$e");
    print("Pilha de chamadas completa:\n$stack");
  }
}
Code language: Dart (dart)

Esse código exibe não só a mensagem de erro, mas também toda a cadeia de chamadas de funções para facilitar a depuração.

D:\dartdemo\firstdart>dart run
Building package executable...
Failed to build firstdart:firstdart:
bin/firstdart.dart:3:13: Error: A value of type 'Null' can't be assigned to a variable of type 'int'.
    int a = null;Code language: PHP (php)

IV. rethrow relançar exceção

Tratar parcialmente e propagar a exceção para cima

Função: executar parte da lógica de recuperação na função atual, depois enviar a exceção para a função chamadora receber tratamento complementar.

Às vezes não conseguimos resolver o erro totalmente na função corrente; precisamos relançar a exceção para que o código chamador também possa lidar com ela.

void misbehave() {
  try {
    dynamic foo = true;
    print(foo++); // true não aceita incremento, causa erro em tempo de execução
  } catch (e) {
    print("Tratamento local em misbehave:${e.runtimeType}");
    rethrow; // Relançar para o bloco try externo capturar
  }
}

void main() {
  try {
    misbehave();
  } catch (e) {
    print("Tratamento final em main:${e.runtimeType}");
  }
}
Code language: Dart (dart)

Fluxo de execução:

Tratamento local em misbehave:NoSuchMethodError
Tratamento final em main:NoSuchMethodError
Code language: PHP (php)

No código acima, o erro é tratado tanto na função misbehave quanto na main.

V. Bloco finally

Executado obrigatoriamente, com ou sem erro

Dois cenários de uso principais:

  1. Apenas try + finally: a exceção não é capturada, o aplicativo crasha após executar o finally
  2. try + catch + finally: tratar o erro primeiro, depois executar finally (exclusivo para liberação de recursos)

1: try + finally

void cleanLlamaStalls() => print("Limpar recursos, bloco executado em qualquer caso");
void breedMoreLlamas() => throw Exception("Ocorreu um erro");

void main() {
  try {
    breedMoreLlamas();
  } finally {
    cleanLlamaStalls();
  }
}
Code language: Dart (dart)

O código de limpeza roda, mas a exceção não capturada encerra o programa no final.

D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Limpar recursos, bloco executado em qualquer caso
Unhandled exception:
Exception: Ocorreu um erro
#0      breedMoreLlamas (file:///D:/dartdemo/firstdart/bin/firstdart.dart:2:27)
#1      main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:6:5)
#2      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#3      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)

2: try + catch + finally

Sintaxe padrão para liberar recursos, por exemplo fechar arquivos abertos

void cleanLlamaStalls() => print("Fechar arquivos / liberar recursos do sistema");
void breedMoreLlamas() => throw FormatException("Falha na análise");

void main() {
  try {
    breedMoreLlamas();
  } catch (e) {
    print("Exceção capturada:$e");
  } finally {
    cleanLlamaStalls();
  }
}
Code language: Dart (dart)

Ordem de execução: lançamento da exceção → tratamento no catch → execução do finally

Resultado da execução

D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Exceção capturada:FormatException: Falha na análise
Fechar arquivos / liberar recursos do sistema
Code language: JavaScript (javascript)

VI. assert: asserções

Funciona apenas em desenvolvimento/depuração, totalmente desativado em produção

assert(condição booleana, [mensagem de erro opcional])

Lança uma AssertionError se a condição for false; ignorado completamente na versão de produção sem perda de desempenho.

1: Exemplo básico de asserção

void main() {
  String? text;
  int number = 120;
  String url = "http://foxdevelop.com";

  assert(text != null); // Verificar se a variável não é nula
  assert(number < 100); // Validar intervalo numérico
  assert(url.startsWith("https")); // Checar protocolo da URL
}
Code language: JavaScript (javascript)

A execução desse código não exibe nada por padrão!

As asserções vêm desativadas por padrão; é necessário ativar um parâmetro de inicialização para usá-las, veja abaixo.

2: Definir mensagem de erro personalizada para asserção falha

void main() {
  String url = "http://test.com";
  assert(
    url.startsWith("https"),
    "O endereço $url deve começar com https",
  );
}
Code language: JavaScript (javascript)

Podemos criar livremente a mensagem exibida quando uma asserção falha.

Como ativar as asserções

  1. Modo Debug do Flutter: asserções ativadas por padrão
  2. Execução via comando dart: dart --enable-asserts nome-do-arquivo.dart
  3. Build de produção: todo código de asserção é removido, sem impacto no desempenho
D:\dartdemo\firstdart\bin>dart --enable-asserts firstdart.dart
Unhandled exception:
'file:///D:/dartdemo/firstdart/bin/firstdart.dart': Failed assertion: line 6 pos 10: 'text != null': is not true.
#0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:67:4)
#1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:49:5)
#2      main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:6:10)
#3      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#4      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)

Tanto dart run quanto o comando simples dart desativam as asserções por padrão, é preciso adicionar a flag --enable-asserts:

Exemplo de comando de execução

dart run --enable-asserts main.dartCode language: CSS (css)

Se o terminal já estiver na raiz do projeto, use a versão curta:

Comando de execução:

dart run --enable-asserts

dart run : Executar código fonte Dart diretamente, ideal para testes de desenvolvimento

dart nome-arquivo : Sintaxe simplificada para rodar um arquivo único

dart compile exe : Compilar um executável independente, as asserções sempre ficam desativadas no binário compilado

Os arquivos Dart ficam na pasta bin do projeto. Você pode navegar até bin para rodar o arquivo diretamente ou subir até a raiz do projeto para executar o projeto completo.

dart run –enable-asserts

Abaixo estão os dois métodos: execução a partir da pasta bin e execução a partir da raiz do projeto.

D:\dartdemo\firstdart\bin>dart --enable-asserts firstdart.dart
Unhandled exception:
'file:///D:/dartdemo/firstdart/bin/firstdart.dart': Failed assertion: line 6 pos 10: 'text != null': is not true.
#0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:67:4)
#1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:49:5)
#2      main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:6:10)
#3      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#4      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)

D:\dartdemo\firstdart\bin>dart run
Building package executable...
Built firstdart:firstdart.

D:\dartdemo\firstdart\bin>cd ..

D:\dartdemo\firstdart>dart run --enable-asserts
Building package executable...
Built firstdart:firstdart.
Unhandled exception:
'file:///D:/dartdemo/firstdart/bin/firstdart.dart': Failed assertion: line 6 pos 10: 'text != null': is not true.
#0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:67:4)
#1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:49:5)
#2      main (file:///D:/dartdemo/firstdart/bin/firstdart.dart:6:10)
#3      _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#4      _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)Code language: PHP (php)

Se a condição da asserção for true, nenhuma exceção será lançada

Modifique o exemplo: troque http por https na URL, altere text != null para text == null e defina number como 99

void main() {
  String? text;
  int number = 99;
  String url = "https://foxdevelop.com";

  assert(text == null); // Verificação de nulo
  assert(number < 100); // Validação de intervalo numérico
  assert(url.startsWith("https")); // Checagem de protocolo URL
}Code language: Dart (dart)

Ao executar novamente, nenhum erro aparece

D:\dartdemo\firstdart>dart run --enable-asserts
Building package executable...
Built firstdart:firstdart.Code language: CSS (css)

VII. Exemplo completo

void cleanResource() => print("finally: liberar recursos ocupados");

void testError() {
  try {
    int num = 150;
    assert(num < 100, "O número deve ser menor que 100");
    throw FormatException("Formato de dados inválido");
  } on FormatException catch (e) {
    print("Exceção de formato capturada:$e");
    rethrow;
  } finally {
    cleanResource();
  }
}

void main() {
  try {
    testError();
  } catch (e) {
    print("main captura a exceção relançada:$e");
  }
}
Code language: PHP (php)

Resultado da execução

D:\dartdemo\firstdart>dart run --enable-asserts
Building package executable...
Built firstdart:firstdart.
finally: liberar recursos ocupados
main captura a exceção relançada:'file:///D:/dartdemo/firstdart/bin/firstdart.dart':
 Failed assertion: line 6 pos 12: 'num < 100': O número deve ser menor que 100Code language: PHP (php)

Exemplo completo de todo o fluxo de gerenciamento de exceções e erros

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *