我有一个在Android上运行的极简主义示例应用程序,仅使用GetX作为状态管理库。有两个屏幕LandingPage和MainScreen。从主屏面返回LandingPage屏面时,控制器未按预期自动处置。我只使用Flutter的导航,而不使用GetMaterialApp Package 。
我的期望是,当Controller被示例化时,由Controller公开的值应该被重置为其初始值。但是,Widget继续显示来自控制器的最后一个值。
我现在使用的是最新版本的Flutter和GetX:2.2.3和4.3.8
感谢你的帮助。
验证码:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.purple,
),
home: LandingScreen(),
);
}
}
class LandingScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.blue[800],
child: Center(
child: ElevatedButton(
onPressed: () => {
Get.to(MainScreen())
},
child: const Text('Navigate to Second Screen'),
),
),
);
}
}
class MainScreen extends StatelessWidget {
final MyController controller = Get.put(MyController());
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
color: Colors.blueAccent,
child: Center(
child: Column(
children: [
Obx(() => Text('Clicked ${controller.count}')),
FloatingActionButton(
onPressed: controller.increment,
child: Text('+'),
),
ElevatedButton(
onPressed: ()=>{Navigator.of(context).pop()},
child: Text('Go Back'),
)
],
),
),
),
),
);
}
}
class MyController extends GetxController {
var count = 0.obs;
void increment() => count++;
}
6条答案
按热度按时间n3ipq98p1#
您需要先使用GetX导航。然而,在写这个答案的时候,有一个bug导致控制器不能自动释放。因此,现在建议使用绑定或从StatefulWidget手动处理它们,直到bug被修复。
11月22日更新2021您仍然可以使用上述解决方案,或者使用更优雅的方法,您可以使用
Bindings
沿着扩展GetView<YourController>
,而不是有状态/无状态Widget。GetXController将提供StatefulWidget所需的大部分功能。您也不必使用GetX导航。这种方法在使用嵌套导航时也有效。
要使用绑定,有多种方法解释here。
c7rzv4ha2#
自动处置
要在移除小部件时释放GetxController,在 *
build()
方法内部 * 使用Get.put
**,而不是作为字段。这是GetX维护人员的正确用法。然后,当
MainScreen
弹出时,可以丢弃控制器。使用错误
控制器不会被释放:
示例化和注册(
Get.put(...)
)不应作为字段。否则,控制器的注册被附加到上面的小部件(即,
LandingScreen
),而不是MainScreen
。只有在LandingScreen
被释放时,MyController
才会被释放。(在问题的代码中,LandingScreen
是“home”Widget,只有在应用程序退出时才会对其进行处理。为什么?
如果将控制器示例化为字段,GetX将记录该控制器的创建,其中上下文 * 当前 * 可用,父小部件的上下文,* 而不是 * 示例化小部件的上下文。示例化小部件上下文直到其
build()
方法才可用。小部件类的示例化和build()
方法的运行是两件截然不同的事情。build()
方法不是widget本身的工厂构造器,而是Flutter框架 * 在 * widget示例化后使用的生命周期方法,用于膨胀widget并将其作为Element
插入/挂载到渲染对象的元素树中。(这是我目前的理解)。在问题的示例中,
MainScreen
小部件在LandingScreen
的上下文中示例化。MainScreen
及其字段位于LandingScreen
的上下文中。MainScreen's build()
方法在示例化后运行。MainScreen's context
在其build()
方法运行时可用,但在Widget示例化期间不可用。为了在释放
MainScreen
时删除/释放MyController
,我们必须在MainScreen
上下文中示例化MyController
,该上下文在调用其build(BuildContext context)
方法时可用。如果我们希望GetX在当前/示例化小部件从小部件树中删除时自动处理GetxController,那么我们应该将它与该上下文相关联。正确用法
现在,当
MainScreen
从路由栈中弹出时,MyController
将被GetX清理/释放(我假设GetX会观察路由历史以了解何时进行清理)。bpzcxfmw3#
你可以像下面这样延迟初始化你的控制器:
在initState函数中:
这会解决你的问题
68de4m5k4#
如果在getMaterialApp上添加路由,则不需要在构建内部启动控制器:
添加'initialRoute'和'getPages'属性,并删除home属性:
在LandingPage()中将Get.to()更改为Get.toNamed():
在主屏幕上,将导航器弹出窗口更改为Get.back():
chy5wohz5#
当我在
controller.dart
文件中定义以下方法时,这对我来说有点工作:延迟Readcontroller控制器;
然后在我的主文件中阅读.dart:
上面这段代码对我来说很好用
给予它一个尝试……
}
mefy6pfw6#
你需要使用getPages与导航getx的方式
路线: