get으로 Page랑 controller를 만들고 이걸 여러 군데에서 재사용해야 할 때가 있어.
뭐 Page(Widget)야 그냥 쓰면 되는데 GetxController의 instance가 독립적으로 생성되게 하기 위해서는 binding할 때 tag 옵션을 줘야해. 예를 만들어 보자구.
먼저 3개의 파일을 만들었어. page_text.dart, page_text_controller.dart 마지막으로 page_text_binding.dart
get으로 page 기본 구성이라고 할 수 있어.
내용은 아래와 같고,
//page_test.dart
class PageTest extends GetView<PageTestController> {//Getview로 선언하면
const PageTest({super.key});
static const routeName = '/ScreenTest';
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() => Text(controller.text)),// Get.find()없이 controller에 접근 가능!
ElevatedButton(
onPressed: () => {controller.text = "Changed!!"},
child: Text("Change the Text!"))
],
),
);
}
}
//page_test_controller.dart
import 'package:get/get.dart';
class PageTestController extends GetxController {
var _text = "Page Test Text".obs;
String get text => _text.value;
set text(String value) => _text.value = value;
}
//page_test_binding.dart
class PageTestBinding extends Bindings {
@override
void dependencies() {
// TODO: implement dependencies
Get.lazyPut(() => PageTestController());//lazyPut => 필요할 때 로딩
}
}
이걸 만약에 navigator에서 GetRoutePage와 함께 사용한다면 다음과 같이 되겠지.
return Navigator(
key: Get.nestedKey(NavKeys.home.index),
initialRoute: ScreenHome.routeName,
onGenerateRoute: ((settings) {
...
return GetPageRoute(
page: () => PageTest(),
binding: PageTestBinding(),
);
...
}
여기까지는 "원래 이렇게 동작하는 거"니까 그렇다치고 이제 test page를 다른 tab에도 넣어서 테스트 해보면!👇👇
controller를 공유해서 다른 탭의 state가 함께 변해.. 당연하겠지만 이건 우리가 원하는 결과가 아니지 ㅎ 이제 tag를 사용해서 이문제를 해결해보도록 하자고. 먼저 binding부터 살펴보면 👇
//page_test_binding.dart
class PageTestBinding extends Bindings {
PageTestBinding({this.controllerTag});
final String? controllerTag;
@override
void dependencies() {
// TODO: implement dependencies
Get.lazyPut(
() => PageTestController(),
tag: controllerTag,//tag 옵션과 함께 dependency 주입!
);
}
}
Get.lazyPut에서 입력받은 controllerTag와 함께 dependency를 주입해. 그리고 Page에서도 마찬가지로 입력받은 controller를 get tag에 override해주자.
class PageTest extends GetView<PageTestController> {
const PageTest({super.key, this.controllerTag});
static const routeName = '/ScreenTest';
final String? controllerTag;
@override
// TODO: implement tag
String? get tag => controllerTag; // get tag override
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() => Text(controller.text)),
ElevatedButton(
onPressed: () => {controller.text = "Changed!!"},
child: Text("Change the Text!"))
],
),
);
}
}
그리고 GetPage나 GetPageRoute할 때 tag만 넣어주면 끝!👇 물론 다른 탭에서 사용하는 Page의 tag는 다른 걸 넣어줘야겠지.
case PageTest.routeName:
return GetPageRoute(
page: () => PageTest(controllerTag: "홈"),
binding: PageTestBinding(controllerTag: "홈"),
);
이렇게 하고 테스트를 해보면 page에 따라서 controller가 개별적으로 잘 동작하는 걸 확인할 수 있어.👇
그 대신 binding을 사용하지 못하는 경우나 page 밖에서 controller에 접근하는 경우에는 반드시 tag를 지정해줘야 해.👇 안 그러면 controller가 주입되지 않았다며 오류가 날거야.
var controller = Get.find<PageTestController>(tag: "홈");
nested navigator가 필요한 프로젝트에서는 이런식으로 tag를 사용하는게 필수가 아닐까 싶어.
그럼 다들 화이팅하라고! 안녕!
'Flutter > Flutter Study' 카테고리의 다른 글
[Flutter] Firestore pagination(무한스크롤) (1) | 2022.11.13 |
---|---|
[Flutter] Bad state: Future already completed (0) | 2022.11.10 |
[소셜차트] 앱 제작기 #7. 네비게이션 시스템 뒤집어 엎기. (2) | 2022.11.02 |
[Flutter] loading 화면 (0) | 2022.10.25 |
[Flutter] Firebase auth email link login (0) | 2022.10.21 |