개발노트

82. [Flutter] GetX 처음 화면으로 이동하기 (until, offAllNamed 차이) 본문

앱 개발/Flutter

82. [Flutter] GetX 처음 화면으로 이동하기 (until, offAllNamed 차이)

mroh1226 2024. 10. 23. 22:54
반응형

문제: 화면 여러개를 거쳐 맨 마지막 화면에 도착했을 때, 처음 화면으로 이동하고 싶다면 GetX에서 네비게이션을 어떻게 해야할까?

 

시나리오: 현재 Get.toNamed() 로 pag1 > page2 > page3 로 네비게이션 한 상태이다.

따라서 현재 화면 위치는 'page3'

여기서 나는 page3, page2 를 닫고 page1으로 이동하고 싶다.

즉, page1이 나올때 까지 화면을 다 닫아버리고 싶다. 

닫아버린 화면들의 GetxController 들은 삭제되어야한다.

 

다만, page1에 Binding 되어있는 GetxController들은 살아있어야한다.

class Page1Binding implements Bindings {
  @override
  void dependencies() {
    Get.lazyPut<Page1Controller>(() => Page1Controller());
    Get.put(View1Controller());
    Get.put(View2Controller());
  }
}

+ 추가적으로 onInit(), onClose() 호출이 일어나는지도 확인해본다.

class Page1 extends GetView<Page1Controller> {
  const Page1({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(child: GetBuilder<Page1Controller>(
        builder: (page1Controller) {
          return Column(
            children: [
              Text(page1Controller.pageName),
              TextButton(
                  onPressed: page1Controller.onPressed,
                  child: const Text('Page2 toNamed')),
              const View1(),
              const View2()
            ],
          );
        },
      )),
    );
  }
}

 

1. Get.until()

Get.until(
      (route) => Get.currentRoute == '/page1',
    );

page2,page3 에 대한 Controller 들이 깔끔하게 제거되며 page1으로 이동했다.

page1에서 Binding 해주었던 자식들까지 살아 남았다.

다만, onInit()은 되지않는구나. 초기화는 되지않는 모습을 볼 수 있다.

🔻이건 lazyPut()으로 ViewController들을 넣었을 때 (page1에서 view1,view2를 사용하면 Controller 생성되는 것 확인)


 

2. Get.offAllNamed()

Get.offAllNamed('/page1');

page1 화면은 뜨지만 Controller 들이 다 삭제된다. 속은 없이 껍데기만 남은 꼴

 

로그를 보면 page1를 새로 띄워서 먼저 이동한 뒤, 기존 page3, page2, page1 을 삭제하는 모습을 볼 수 있다.


onInit()과 onClose() 호출 로그로 보아하니 Controller 또한, page1Controller를 onInit() 하고 기존에 있던 page3, page2, page1 Controller를 onClose() 한다.


page1Controller는 Get.put 으로 관리되니.. 하나의 인스턴스만 존재하고,

맨 앞에서 onInit() 했지만 나중에 page1Controller가 onClose()가 호출되면서 인스턴스가 onDelete()되어 없어져버린다.


다른 이동하는 방법도 다 알아봤는데.. 최선은 Get.Until() 인 것 같다.

(만약 초기화도 필요하다면??)

Get.until(
      (route) => Get.currentRoute == '/page1',
    );
Get.toNamed('/page2');

 

아 설마했는데 Get.until()로 page2 초기화를 목표로 전화면인 page1으로 이동한 다음 toNamed() 로 page2로 이동하면 page2Controller가 삭제됨..

 

근데 한번 더 돌리면 이때는 바인딩 타고 생성함 onInit() 으로
(계속 해보니 짝수 번째 시도에는 원하는 것 처럼 Controller가 만들어지고, onInit() 을 수행했다.)

그 차이는 (인스턴스가 지워진 상태일때 = 짝수번째 시도) 일때는 Controller가 만들어지고 onInit() 을 수행했다.


그럼.. toNamed()로 화면 이동 전에 이동할 화면의 컨트롤러를 지워주는 로직이 필요하다는 이야기네

 

- 해결되지않은 비슷한 네비게이션 문제들
https://github.com/jonataslaw/getx/issues/1955

 

Get.offAllNamed() removes destination's controller · Issue #1955 · jonataslaw/getx

Describe the bug Get.offAllNamed(destination) cleans up destination controller immediately, when going from HomePage to OtherPage and back to HomePage. i.e currently at /home and call Get.toNamed('...

github.com

https://github.com/jonataslaw/getx/issues/2563

 

GetX dispose Controllers of the Parent Page, that are still in use · Issue #2563 · jonataslaw/getx

Describe the bug GetX dispose Controllers of the Parent Page, that are still in use. This happens when we navigate to multiple screens at the same time(When we want to build a navigation backstack)...

github.com

 

글을 읽어보면

Get.toNamed()

 

이게 바인딩을 타는게 절대적이지 않은 것 같다.


위 글들 처럼 Get.until 이나 Get.offAllNamed 나 다른 네비게이션 스택에서 화면을 제거하고 곧바로 Get.Named()로 화면이동을 한다면, 바인딩을 타고 Controller가 생성되어야하는데 그렇지 않다...

 


일단은 Get.until()로 이동할 화면의 Controller를 유지하여 화면을 이동한다.

이동된 화면에 재렌더링이 필요하다면 이동 전에 update() 가 포함된 메소드를 호출하는 것으로 해결
초기화 필요 시, onInit() 도 써도 잘된다.

//이동 화면의 필요한 부분만 재랜더링하기 위해 update() 포함된 메소드 호출
Get.find<ChatListController>().addList(); 

//전체 초기화는 onInit() 사용
Get.find<ChatListController>().onInit();

 

반응형
Comments