[GetX] 컨트롤러가 제때 안 죽을 때

Broccolism·2021년 9월 2일
7

dev-story

목록 보기
2/9

3줄 요약
1. 컨트롤러는 페이지가 닫혀도 죽지 않음
2. Get.toNamed()를 사용하면 스크린이 나온 뒤에 할 일을 추가로 적을 수 있음
3. 데이터 초기화 함수를 잘 활용하면 컨트롤러 1개로 여러 스크린 커버 가능

🚨 컨트롤러가.. 왜 안 죽지?

유저의 프로필 정보를 받아오는 UserProfileController 가 있었다. 어느 화면에서든 유저의 프로필 사진이나 닉네임을 누르면, 그 사람 프로필로 이동하면서 이 컨트롤러를 계속 사용하게 되었다.

  • naive implementation
    에.. 컨트롤러가 초기화 될 때 유저 정보를 받아오면 되니까 onInit() 함수에서 데이터를 받아오면 되겠지?
// UserProfileController
 onInit() async {
  await getData();
  super.onInit();
}
  • 문제점

    유저 A의 프로필을 봄 -> 뒤로가기 -> 유저 B의 프로필을 보고싶음

컨트롤러는 화면이 닫힐 때 같이 close 되지 않는다. 컨트롤러의 생명주기와 위젯의 생명 주기는 완전 별개의 것이다. 생각해보면 컨트롤러 입장에서 화면이 닫혔는지 아닌지 알 방법이 없다!
따라서 유저 A의 프로필을 본 뒤, 유저 B의 프로필을 보러 들어갔을 때에는 기존 컨트롤러가 계속 살아있는 상태이고 컨트롤러가 초기화 될 때 불리는 onInit() 함수는 절대 불리지 않는다. 결국 유저 B의 프로필 사진을 눌러서 들어간 스크린에 유저 A의 데이터가 보여지게 된다.

🧐 그럼.. 화면이 닫힐 때마다 컨트롤러를 억지로 죽여야 하나?

  • 그렇게 되면 매번 컨트롤러를 새로 메모리에 올리고, 변수를 초기화 해주는 등 너무 많은 cost가 든다.
  • 또한 getX에서 이를 지원하는 함수가 특별히 없어보인다. getX의 철학을 무시하는 일이기 때문이다.

✅ 그러면 컨트롤러 안에 있던 애들만 죽이자

UserProfileController에 함수 하나를 만든다.

// UserProfileController

void removeData() {
  _userProfile.value = null;
}

그리고 다른 사람의 프로필로 이동할 때마다 기존 데이터를 지우고 스크린을 띄워준다.

// view

UserProfileController.to.removeData();
Get.toNamed( ... );
await UserProfileController.to.getUserProfile();
UserProfileController.to.getReviews();

특이한건, Get.toNamed() 이후의 코드도 실행이 잘 된다는 점이다. 그러니까 이 코드대로라면 데이터 삭제 -> 새 스크린으로 이동 -> 데이터 불러오기의 순서대로 작동하기 때문에, 처음에는 아주 잠깐 하얀 화면이 보였다가 유저 프로필이 제대로 보이게 된다.

✅✅ 기존에 있던 데이터를 꼭 지워야 하는 상황에만 죽이자

만약 이런 시나리오라면 굳이 컨트롤러의 데이터를 지우고 정보를 다시 받아올 필요가 없다.

유저 A의 프로필을 봄 -> 뒤로가기 -> 유저 A의 프로필을 다시 보고싶음

어차피 동일한 데이터를 보여줘야 하기 때문이다. 그래서 컨트롤러 안에 기존에 열람한 유저 프로필의 아이디와 새롭게 보려는 유저 프로필의 아이디가 같은지 확인하는 함수를 만들었다. 만약 같다면 아무 일도 일어나지 않고, 다르다면 데이터 삭제 -> 새 스크린으로 이동 -> 데이터 불러오기 의 과정을 거치게 된다.

profile
설계를 좋아합니다. 코드도 적고 그림도 그리고 글도 씁니다. 넓고 얕은 경험을 쌓고 있습니다.

1개의 댓글

comment-user-thumbnail
2023년 11월 15일

안녕하세요~
이 글 덕분에 힌트를 얻은것 같네요~
질문이 있어요!
혹시 get.put(Controller()); 를 주입시켜줬음에도 불구하고
해당 screen 으로 페이지 이동하고면 (Get.back() -> 페이지 재방문 * 무한반복) 가끔가다가 해당 컨트롤러를 못찾는다는 에러가 출력되더라구요..
혹시 이런 경험 있으셨을까요??

GetPage(
 name:'',
 page: () => Screen(),
 binding: BindinsBuilder(() => Get.put(Controller()))
)
 class Screen extends GetView<Controller> {
 
 
Widget build() {
... controller 사용.,,, 하는데 가끔씩 controller not found 가 뜨더라구요.. 
}
}
답글 달기