Flutter GetX中GetBuilder的init方法为何无法返回指定Controller?
问题:GetBuilder中init参数传入Get.find获取的Controller实例为何tag未生效?
我尝试为同一CountController创建带唯一tag的不同实例,但使用init:Get.find<CountController>(tag: "myController")时出现异常:builder方法中的controller的tag为类默认值null,但Get.find能获取到tag为myController的实例;而注释init、启用tag: "myController"参数则能得到预期结果。请问为何第一种方式中init未生效?
相关代码
controller.dart
import 'package:get/get.dart'; class CountController extends GetxController { String? tag = "null"; RxInt count = RxInt(1); CountController({this.tag, int? value}) { if(value != null) count = RxInt(value); } void increment(){ if(count.value == 24) { Get.closeAllSnackbars(); Get.snackbar("Item Count", "You can't increase count more!"); return; } count.value++; update(); } void decrement(){ if(count.value == 1) return; count.value--; update(); } }
Test.dart
import 'package:flutter/material.dart'; import 'package:food_app/controllers/count_controller.dart'; import 'package:get/get.dart'; class Test extends StatelessWidget { Test({Key? key}) : super(key: key){ Get.put(CountController(tag: "myController"), tag: "myController"); } @override Widget build(BuildContext context) { return GetBuilder<CountController>( init: Get.find<CountController>(tag: "myController"), //tag: "myController", builder: (controller){ print("with Get.find has tag: ${Get.find<CountController>(tag: "myController").tag}"); print("controller from builder has tag: ${controller.tag}"); return Scaffold(body: Center(child: Text("Hello Flutter"))); }, ); } }
打印结果对比
使用init时:
I/flutter ( 4290): with Get.find has tag: myController I/flutter ( 4290): controller from builder has tag: null
使用tag参数时:
I/flutter ( 4290): with Get.find has tag: myController I/flutter ( 4290): controller from builder has tag: myController
原因分析与解决方案
核心原因
GetBuilder的init参数不是用来传入已存在的Controller实例,而是用于:当GetBuilder内部在依赖容器中找不到对应tag的Controller时,创建一个新的实例并初始化。
你遇到的问题逻辑是:
- 你通过
Get.put已经把tag为myController的实例存入了Get的依赖容器 - 但你只给GetBuilder传了
init,没传tag——此时GetBuilder会忽略你传入的init实例,反而自动创建一个不带tag的默认CountController实例(因为没有指定tag,GetBuilder无法定位到你之前存入的实例),所以builder里拿到的是这个新创建的默认实例,tag自然是类默认值null - 而当你启用
tag: "myController"时,GetBuilder会直接根据tag从依赖容器中查找对应的实例,这时候就会拿到你之前Get.put的那个正确实例,tag也正常显示。
正确用法
如果你想复用已存在的Controller实例,有两种正确方式:
方式一:只指定tag参数,无需init
这是最直接的方式,让GetBuilder直接从容器中获取对应tag的实例:GetBuilder<CountController>( tag: "myController", builder: (controller){ // 这里的controller就是你之前Get.put的实例 }, )方式二:同时指定tag和init(用于懒加载初始化)
如果需要在容器中没有对应实例时才初始化,可同时传tag和init,此时GetBuilder会先检查容器中是否有该tag的实例,没有则用init创建并存入:GetBuilder<CountController>( tag: "myController", init: CountController(tag: "myController"), builder: (controller){ // ... }, )
内容的提问来源于stack exchange,提问作者Susano
相关产品推荐
相关产品推荐

