외부에서 Json이나 csv 파일을 비동기로 불러올 때 일반적으로 발생할 수 있는 에러들의 처리 방법입니다.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class Test extends StatefulWidget {
const Test({Key? key}) : super(key: key);
@override
State<Test> createState() => _TestState();
}
class _TestState extends State<Test> {
@override
void initState() {
super.initState();
try {
// 데이터 불러오기
// http.Response response = await http.get(site);
} on SocketException {
// 인터넷 연결 확인
failure('인터넷 연결을 할 수 없습니다.', false);
} on FormatException {
// 지정된 데이터 형식이 없거나 다른경우
failure('데이터를 읽어 오지 못했습니다.', false);
} on HttpException {
// 인터넷 페이지를 못 찾았을 때
failure('지정된 페이지를 찾을 수 없습니다.', false);
} catch (e) {
failure(e.toString(), false);
}
}
void failure(String message, bool isCheck) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(
context: context,
barrierDismissible: false,
builder: (builder) {
return AlertDialog(
title: const Text('오류'),
content: Text(message),
actions: [
isCheck
? ElevatedButton(
onPressed: () => SystemNavigator.pop(),
child: const Text(
'종료',
style: TextStyle(fontSize: 18, color: Color.fromARGB(255, 237, 231, 255)),
),
)
: ElevatedButton(
onPressed: () {
// 확인 버튼 처리
},
child: const Text(
'확인',
style: TextStyle(fontSize: 16, color: Color.fromARGB(255, 237, 231, 255)),
),
),
],
);
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Text('Test'),
);
}
}
@override
void initState() {
super.initState();
try {
// 데이터 불러오기
// http.Response response = await http.get(site);
} on SocketException {
// 인터넷 연결 확인
failure('인터넷 연결을 할 수 없습니다.', false);
} on FormatException {
// 지정된 데이터 형식이 없거나 다른경우
failure('데이터를 읽어 오지 못했습니다.', false);
} on HttpException {
// 인터넷 페이지를 못 찾았을 때
failure('지정된 페이지를 찾을 수 없습니다.', false);
} catch (e) {
failure(e.toString(), false);
}
}
initState에서 외부에서 비동기로 데이터를 불러올 때 try / catch를 사용합니다.
이때 여러 오류들 중 가장 일반적인 에러들을 간단히 처리해주는 명령어들이 dart:io에 포함되어 있습니다.
on SocketException {
// 인터넷 연결 확인
failure('인터넷 연결을 할 수 없습니다.', false);
}
인터넷 연결에 문제가 있다면 처리할 수 있는 부분입니다.
on FormatException {
// 지정된 데이터 형식이 없거나 다른경우
failure('데이터를 읽어 오지 못했습니다.', false);
}
가져오고자 하는 데이터와 받는 곳의 데이터형식이 다르거나 없을 경우에 처리 하는 부분 입니다.
on HttpException {
// 인터넷 페이지를 못 찾았을 때
failure('지정된 페이지를 찾을 수 없습니다.', false);
}
지정된 페이지의 주소가 맞지 않을 경우 HttpException에서 처리하게 됩니다.
catch (e) {
failure(e.toString(), false);
}
마지막으로 기타 오류를 처리하게 됩니다.
그리고 failure 함수는 이런 에러 메시지를 Dialog를 통해 화면에 표시해 줍니다.
문제는 일반적인 방법으론 initState 안에선 위젯을 표시할 수 없지만
WidgetsBinding.instance.addPostFrameCallback 을 통해 사용할 수 있습니다.
void failure(String message, bool isCheck) {
WidgetsBinding.instance.addPostFrameCallback((_) {
showDialog(
context: context,
barrierDismissible: false,
builder: (builder) {
return AlertDialog(
title: const Text('오류'),
content: Text(message),
actions: [
isCheck
? ElevatedButton(
onPressed: () => SystemNavigator.pop(),
child: const Text(
'종료',
style: TextStyle(fontSize: 18, color: Color.fromARGB(255, 237, 231, 255)),
),
)
: ElevatedButton(
onPressed: () {
// 확인 버튼 처리
},
child: const Text(
'확인',
style: TextStyle(fontSize: 16, color: Color.fromARGB(255, 237, 231, 255)),
),
),
],
);
});
});
}
String message와 bool isCheck를 받으며 message는 오류 메시지를 isCheck는 앱 시작 부분에서 문제가 생길 경우 오류 메시지를 표시함과 동시에 앱을 종료시킬 때 또는 일반 에러 메시지의 표시를 구분하기 위한 것입니다.
현재 위 코드는 한 라인에서 적용했기에 context를 바로 받았지만 failure을 별도로 지정한다면 BuildContext를 받아 오시면 됩니다.
아니면 GetX를 사용하시면 context 없이 사용하실 수 있습니다.
WidgetsBinding.instance.addPostFrameCallback((_) {
// 화면 표시 위젯
});
만약 이 부분에 문제가 생긴다면 아래 코드로 사용해 보시기 바랍니다.
T? _ambiguate<T>(T? value) => value;
_ambiguate(WidgetsBinding.instance)!.addPostFrameCallback((_) {
// 화면 표시 위젯
});
'Flutter' 카테고리의 다른 글
플러터(Flutter) - 삼항연산자 (0) | 2024.07.09 |
---|---|
플러터(Flutter) 3.0 - QR Code Scanner 검은 화면 해결(qr_code_scanner) (0) | 2022.06.21 |
플러터(Flutter) - QR Code Scan (0) | 2022.01.26 |
플러터(Flutter) - 이미지 메뉴(Image Menu) (0) | 2022.01.17 |
플러터(Flutter) - 앱의 폰트 크기 유지 (0) | 2021.05.01 |