Tratamento de erros
O tratamento de erros é a forma de lidar com problemas que podem acontecer durante a execução do programa. Dentre as possibilidades, temos:
- Converter texto inválido para número
- Abrir arquivo que não existe
- Dividir valor incorreto
- Conectar em um serviço indisponível
- Receber dados inválidos do usuário
Em Dart, erros normalmente são tratados com:
- try
- catch
- on
- finally
- throw
Erro sem tratamento
Veja um exemplo de código que não possui tratamento de erro (vai dar erro):
void main() {
String entrada = 'abc';
int numero = int.parse(entrada);
print(numero);
}
Esse código tenta converter 'abc' para inteiro, mas 'abc' não é um número e sim uma string.
Usando try e catch
Ainda usando o exemplo de Erro sem tratamento, vamos usar o try para escrever o código que pode causar um erro e depois um catch para tratar esse erro caso aconteça.
void main() {
String entrada = 'abc';
try {
int numero = int.parse(entrada);
print(numero);
} catch (erro) {
print('Valor inválido');
}
}
Capturando o erro e o stack trace
O catch pode receber dois valores:
catch (erro, stackTrace)
O erro é o erro gerado, se usarmos ele como variável $erro, vamos ver qual erro foi emitido, como exemplo: FormatException: Invalid radix-10 number.
Já o stackTrace guarda o caminho interno do erro, o que é útil para debug.
Usando on
Se quisermos tratar um tipo específico de erro, devemos usar o on.
void main() {
String entrada = 'abc';
try {
int numero = int.parse(entrada);
print(numero);
} on FormatException {
print('O texto informado não é um número válido');
}
}
Usando on com catch
Nós podemos ainda usar on e catch juntos.
void main() {
String entrada = 'abc';
try {
int numero = int.parse(entrada);
print(numero);
} on FormatException catch (erro) {
print('Erro de formato: $erro');
} catch (erro) {
print('Erro desconhecido: $erro');
}
}
Isso é útil para capturar um erro específico e ainda capturar qualquer outro erro que não foi tratado.
Usando finally
O bloco finally é usado para executar algo no final, independente se houve erro ou não. Ele é muito útil para liberar recursos, fechar arquivos, encerrar conexões, etc.
void main() {
String entrada = '123';
try {
int numero = int.parse(entrada);
print('Número: $numero');
} catch (erro) {
print('Erro: $erro');
} finally {
print('Fim da operação');
}
}
Uma dica é usar o finally para ações que precisam acontecer sempre.
Lançando erro com throw
Podemos gerar um erro manualmente usando throw.
double sacar(double saldo, double valor) {
if (valor <= 0) {
throw Exception('Valor de saque inválido');
}
if (valor > saldo) {
throw Exception('Saldo insuficiente');
}
return saldo - valor;
}
void main() {
try {
double saldoFinal = sacar(100.00, 150.00);
print('Saldo final: $saldoFinal');
} catch (erro) {
print('Erro: $erro');
}
}
Criando uma exceção própria
Podemos criar nossa própria classe de exceção.
class SaldoInsuficienteException implements Exception {
String mensagem;
SaldoInsuficienteException(this.mensagem);
@override
String toString() {
return 'SaldoInsuficienteException: $mensagem';
}
}
double sacar(double saldo, double valor) {
if (valor > saldo) {
throw SaldoInsuficienteException('Saldo disponível: R\$ $saldo');
}
return saldo - valor;
}
void main() {
try {
double saldoFinal = sacar(100.00, 150.00);
print(saldoFinal);
} on SaldoInsuficienteException catch (erro) {
print(erro);
}
}
tryParse: alternativa melhor para conversão
Nem sempre precisamos usar try/catch. Quando vamos converter texto em número, o Dart possui o tryParse.
void main() {
String entrada = 'abc';
int? numero = int.tryParse(entrada);
if (numero == null) {
print('Número inválido');
} else {
print('Número: $numero');
}
}
O tryParse tenta converter o texto para inteiro, se conseguir, retorna um int. Se não conseguir, retorna null.
9.14 rethrow
Use rethrow quando você captura um erro, faz alguma ação e quer lançar o mesmo erro novamente.
void processarPagamento() {
try {
int.parse('abc');
} catch (erro) {
print('Registrando erro no log: $erro');
rethrow;
}
}
void main() {
try {
processarPagamento();
} catch (erro) {
print('Erro tratado na main: $erro');
}
}