일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- InkWell
- node.js
- Image.network
- Row
- Flutter 강좌
- ListView.builder
- navigator
- Cached Image
- Scaffold
- 반석천
- HTTP
- flutter
- Flutter Tutorial
- MainAxisAlignment
- AppBar
- Column Widget
- Snackbar
- listview
- Flutter Example
- CrossAxisAlignment
- sqlite
- Row Widget
- Flutter 앱 배포
- WillPopScope
- Networking
- FutureBuilder
- Hello World
- Load Image
- ListTile
- Flutter 예제
- Today
- Total
꿈꾸는 시스템 디자이너
GetX를 이용할 때 값이 변경되지 않는 경우 본문
GetX란 Flutter앱의 상태관리에 사용되는 패키지로 Provider와 유사한 기능을 제공한다.
Provider에 비해 보다 가벼우며 더 강력하다고 하는데 기존의 Provider 대비 보다 다양한 기능을 제공하고 있다. 그래서 복잡하기도 하다.
여튼, GetX에서는 상태관리를 위해 GetxController를 상속하는 Controller 클래스를 만들고 그 클래스 안에 상태관리하고자 하는 변수나 인스턴스들을 배치해서 사용하게 된다.
Flutter의 기본 타입(Int, String 등)의 경우 Obx()를 이용해서 상태값 변경을 플랫폼이 인지하고 자동으로 그 값이 갱신되는데 직접 구현한 클래스 타입의 인스턴스의 경우 상태값 변경이 발생해도 값 변경 인지가 안되는 경우가 발생했다.
본인의 경우 데이터 모델 클래스들을 가지는 슈퍼클래스를 이용해서 각 모델의 값을 하나의 인스턴스로 관리하고자 했다. 예를 들어 다음과 같은 방식이다.
Resource
ㄴ Worker
ㄴ Device
ㄴ Car
Resource 클래스 안에 Worker, Device, Car 클래스의 인스턴스가 존재하는 형태였는데 서버에 로그인할 때마다 해당 값을 한번에 수신해서 GetController안의 Resource 인스턴스에 주입하는 방식으로 사용했고 동작도 잘 했다.
문제는 작업자의 정보를 서버에 변경하고 그 결과를 수신하여 Resource.Worker에 주입하려고 하니 Worker의 변경사항이 화면에 갱신되지 않는 문제가 발생했다. 실제 로그로 찍어보면 모델 데이터는 변경된 것이 맞으나 변경 사항이 위젯으로 전달되지 않는 것이 이유였다.
현재 파악한바로는...
임의의 클래스 인스턴스를 상태값으로 관리할 경우 그 내용이 변경되다고 해서 위젯에 통보되는 것이 아닌 것 같다. 상태값 인스턴스의 값이 변경되는 것만으로는 변경사실이 위젯으로 통보되지 않았다.
해당 상태값 인스턴스에 새로운 인스턴스를 생성해서 대입하는 경우에만 연결된 위젯으로 변경사실이 통보되는 것을 확인할 수 있었다.
그럼 해결방법은?
해결방법은 의외로 간단했는데 update함수를 이요하는 것이었다.
아래와 같이 상태값 인스턴스(signInResource)에 update함수를 호출해서 signInResource.worker값을 변경하면 연결된 위젯에 갱신이 발생하다.
signInResource.update((val) {
val.worker = OasisWorker.fromJson(jsonDecode(_payload.data));
});
[update: 2021-07-19]
ListVew를 사용하면서 갱신된 상태값이 UI에 잘 반영되지 않는 현상이 있었다.
조금 검색해보니 refresh 명령어를 통해 명시적으로 UI에 반영하는 방식이 있었다.
signInResource.value.worker = OasisWorker.fromJson(jsonDecode(_payload.data));
signInResource.refresh();