2024. 6. 20. 16:14ㆍProgramming/Flutter
Flutter를 사용해서 코드를 작성하는 도중, 다음과 같은 에러가 발생했다.
{Provider} was used after being disposed.
notifyListener()
를 호출하는 비동기 함수를 실행한 뒤, 함수 실행이 완료되기 전에 다른 페이지로 이동했기 때문에, dispose()
가 호출된 다음 notifyListener()
가 호출되어 발생한 에러 문구다. State
에는 mounted
라는 상태값이 있어서 dispose()
가 된 이후에는 setState()
를 호출하지 않을 수 있었으나, Provider
는 기본적으로 dispose()
가 실행됐는지 확인할 방법을 알려주지 않는다. 비동기 함수를 다루다보면 쉽게 만날 수 있는 문제여서 그런지, 에러 문구를 구글링해보니 쉽게 대응 방법을 찾을 수 있었다. 스택 오버플로우: Flutter changeNotifier was used after being disposed에 달려있는 답변을 살펴보니, ChangeNotifier
에서 제공하는 notifyListener()
와 disepose()
를 override해서 쉽게 해결할 수 있었다. 문제를 해결하기 위해 ChangeNotifier
를 상속받아서 작성한 코드는 다음과 같았다.
class CustomChangeNotifier extends ChangeNotifier {
bool _isMounted = false;
bool get isMounted => _isMounted;
@override
void dispose() {
_isMounted = false;
super.dispose();
}
@override
void notifyListeners() {
if (_isMounted) {
super.notifyListeners();
}
}
}
간단하다. 만들어놓고 곰곰히 생각해보니 비동기 요청을 하는 동안 프로그레스 인디케이터를 표시하고, 요청이 완료되면 프로그레스 인디케이터를 숨김 처리하는 페이지가 상당히 많았다. 기왕 ChangeNotifier
를 상속받은 김에, 비동기 함수가 실행중인지 아닌지 여부를 체크하기 위한 상태값 _isFetching
을 추가해보는 것은 어떨까. 또한 함수 내에서 비동기 처리를 실행하기 전에 _isFetching
을 true
로 변경한 뒤 notifyListener()
를 호출하고, 비동기 처리가 완료된 뒤에는 _isFetching
을 false
로 변경한 뒤 notifyListener()
를 호출하게 하면, 각 페이지마다 수동으로 코드를 작성할 필요가 없지 않을까.
이를 위해서 다음과 같이 _isFetching
값을 추가하고, 비동기 함수를 처리하기 위한 함수를 추가했다.
class CustomChangeNotifier extends ChangeNotifier {
bool _isMounted = false;
bool get isMounted => _isMounted;
bool _isFetching = false;
bool get isFetching => _isFetching;
set isFetching(bool value) {
_isFetching = value;
notifyListener();
}
Future<T> asyncHandler(Future<T> Function() handler) async {
isFetching = true;
T result = await handler();
isFetching = false;
return result;
}
@override
void dispose() {
_isMounted = false;
super.dispose();
}
@override
void notifyListeners() {
if (_isMounted) {
super.notifyListeners();
}
}
}
새로 추가한 asyncHandler()
는 인자로 전달받은 handler()
를 실행하기 전에 isFetching
을 true
로 변경해주고, handler()
가 동작이 완료되면 isFetching
을 false
로 변경해준다. 이걸로 Provider
를 사용하는 페이지에서 비동기를 처리하기가 조금 더 쉬워졌다. 와! 고민 해결! ' ㅇ')
'Programming > Flutter' 카테고리의 다른 글
Pigeon을 사용해서 여러개의 인터페이스를 생성할 때 발생할 수 있는 에러 정리 (0) | 2024.06.24 |
---|---|
Pigeon을 사용하여 Type-safety한 네이티브 코드 작성하기 (0) | 2024.06.21 |
최상위 Navigator와 MaterialApp, 그리고 Navigator.push()와 GetX.to() (0) | 2022.07.05 |
[Flutter] isolate와 SharedPreferences, 그리고 파일에 대한 접근 2 (0) | 2022.06.10 |
[Flutter] 백그라운드에서 띄운 푸시 알람 메시지를 터치해서 앱을 실행했을 때, getInitialMessage()가 동작하지 않는다. (0) | 2022.02.04 |