그러나 두 블로그 다 내 상황에서는 동작하지 않았다. 무엇보다 하위 위젯인 ErrorWidgetBuilder 에 onError 메소드와 builder 를 전달했다한들 에러 발생시 ErrorHandlerWidget의 빌더가 렌더링 될 여지가 없는데 이게 동작한다는 게 이해되지 않았다.
혹시 지금 내 프로젝트에선 main 위젯에서 MaterialApp위젯을 순수하게(?) 쓰는게 아니라 MaterialApp.router 네임드생성자에 riverpod Provider로 생성한 goRouter 객체를 넘겨서 라우팅을 하고 있어서 위젯트리가 다르게 생성되나? 그래서 re-render 조건이 달라지는 걸까? 이건 한 번 다른 예제 프로젝트를 만들어서 검증해보아야겠다.
새로운 아이디어가 필요했다.
# 어떻게 해결했냐면요.
위에서 밝혔다시피 내 프로젝트는 riverpod과 go_router로 환경 설정을 했다.
라우터 설정은 다음과 같다.
이것이 나의 최고의 아웃풋이었다... 허허..
그림은 구리지만.. 어떤 경로에서 접근하든 초기 라우트를 제외하고는 어떤 페이지로 이동하든 DashboardScreen을 거쳐야 했다. DashboardScreen은 Bottom Navigation을 보여줄지 여부, 음악이 재생중인지 Stream을 열어두고 음악 재생관련 UI를 보여줄지 등등을 관리했다.
그렇다면 에러도 여기서 처리하면 되지 않을까 싶었다. 새로운 페이지를 렌더링하다가 에러가 발생하면 감지했다가 에러 페이지로 리렌더링 하면 되것지.. 했던 것.
1. re-render를 시킬 수 있는 조건을 위해 변수 shoErrorPage를 선언했다. 기본값은 false
2. initState에서 렌더링시 발생하는 모든 에러를 캐치하는 FlutterError.onError 에 콜백메서드를 전달했다. 수행하는 내용은 print로 콘솔 메시지를 남기고 showErrorPage 값을 true로 바꿔준 뒤, 모든 위젯 바인딩이 종료되었을 때 setState로 변경된 showErrorPage에 따른 re-render를 하는 것.
-> print 부분은 서버에 로그를 전송하든, 로거로 로그를 남기든.. 에러를 트래킹할 수 있는 다양한 방법을 사용하면 된다.
3. build() 에서는 showErrorPage에 따라서 에러페이지를 보여줄지, 정상 상태일 때 렌더링될 페이지를 보여줄지 분기를 나눴다.
에러 스크린은 각자 알아서 원하는 대로 정의하시면 될듯!!
# 결과
일부러 오류상황을 만들어 테스트 한 결과 제대로 잘 됐다.
네트워크 Exception시에도 위 방법을 활용해 네트워크 오류 페이지로 이동할 수 있게 만들고 싶은데.. 일단 우선순위 높은 다른 일부터 처리하고 해야겠다.
만약 해당 프로젝트처럼 에러페이지가 아닌 다이얼로그로 처리하고 싶은 사람들은 showDialog를 조건에 따라서 호출하면 될 것 같다.