-
[Flutter] Flutter Hook에서 WebView가 포함된 비동기 함수를 useEffect에서 선언했을 때 나오는 Zone mismatch 에러에 대해서...Flutter 2024. 9. 3. 18:21
요즘 기존의 Stateful, Stateless, Consumer Widget... 등등을 HookWidget, HookConsumerWidget으로 수정하는 작업을 하고 있는데, 이때 발생한 Zone mismatch 에러에 대해서 정리해보려고 한다.
기존 코드
import 'package:project_name/common/const/color.dart'; import 'package:desktop_webview_window/desktop_webview_window.dart'; import 'package:flutter/material.dart'; class WebviewScreen extends StatefulWidget { const WebviewdScreen({super.key}); @override State<WebviewScreen> createState() => _WebviewScreenState(); } class _WebviewScreenState extends State<WebviewScreen> { @override void initState() { super.initState(); _openWebview(); // 요 부분 } @override Widget build(BuildContext context) { return Center( child: Container( decoration: BoxDecoration( color: BUTTON_PRESS_COLOR, borderRadius: BorderRadius.circular(100), ), height: 200, width: 200, child: IconButton( onPressed: () { _openWebview(); }, icon: Image.asset( 'asset/image/webview_icon.png', color: Colors.white, height: 130, ), ), ), ); } void _openWebview() async { const url = "https://google.co.kr"; final webview = await WebviewWindow.create(); webview.launch(url); } }
HookWidget 으로 바꾼 코드
import 'package:project_name/common/const/color.dart'; import 'package:desktop_webview_window/desktop_webview_window.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; class WebviewScreen extends HookWidget { const WebviewScreen({super.key}); @override Widget build(BuildContext context) { useEffect((){ _openWebview(); return; },[]); return Center( child: Container( decoration: BoxDecoration( color: BUTTON_PRESS_COLOR, borderRadius: BorderRadius.circular(100), ), height: 200, width: 200, child: IconButton( onPressed: () { _openWebview(); }, icon: Image.asset( 'asset/image/webview_icon.png', color: Colors.white, height: 130, ), ), ), ); } void _openWebview() async { const url = "https://google.co.kr"; final webview = await WebviewWindow.create(); webview.launch(url); } }
이렇게 수정했는데 onPressed를 눌러 버튼을 동작할 때 마다,
이런 에러가 발생했다.
찾아보니 Flutter는 이벤트 루프와 같은 실행 컨텍스트를 관리하기 위해 Zone을 사용하는데, desktop_webview_window 라이브러리에서 사용되는 WebView가 Flutter가 처음 실행된 Zone과 다른 Zone에서 호출되면서 이러한 문제가 발생한다고 한다.
이를 내 코드에 대입해 보면 비동기 함수(Webview)를 StatefulWidget의 initState에서 실행시켰을 때는 Zone mismatch 에러가 안나지만 HookWidget의 ueseEffect 안에서 실행시켰을 때는 나는 이유는
- StatefulWidget의 initState는 Flutter의 기본 Zone에서 실행되기 때문에 WebView를 초기화하는 코드가 메인 UI Zone에서 실행되지만
- HookWidget의 useEffect는 Hooks 라이브러리에서 제공하는 훅으로 Flutter 위젯의 생명주기와 연결되어 실행된다. 때문에 비동기 코드가 실행될 때 다른 Zone에서 실행될 수 있다.
해결방법
Flutter Hook의 useEffect에서 비동기 함수 같은 함수들을 사용할 때에는
WidgetsBinding.instance.addPostFrameCallback 안에 원하는 함수를 넣어 다음과 같이 사용하면 된다.
useEffect(() { WidgetsBinding.instance.addPostFrameCallback((_) { _openWebview(); }); return; }, []);
'Flutter' 카테고리의 다른 글
[Dart] 변수 선언 시 var와 그 외의 타입을 지정하는 경우 (0) 2024.01.15 [Flutter] private 변수(_)에 대해서... (0) 2023.12.20 [Flutter] Don't invoke 'print' in production code. 뜨는 이유 (0) 2023.12.18 [Flutter] TextFormField 함수 정리 (0) 2023.11.14 [Dart] extends와 implements의 차이?? (2) 2023.11.02