找不到 XXXController 您需要调用 Get.put 或 Get.lazyPut
XXXController not found you need to call Get.put or Get.lazyPut
我正在尝试使用下一个布局创建简单的应用程序:
按钮应该切换 Widget1\Widget2。
我写了下一个代码(复制过去):
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get_core/src/get_main.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
initialBinding: HomeBinding(),
initialRoute: '/widget1',
home: Scaffold(
appBar: AppBar(
title: Text("Demo"),
),
body: SafeArea(
child: IndexedStack(
index: Get.find<NavigationBarController>().tabIndex.value,
children: [
Widget1(),
Widget2()
],
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: Get.find<NavigationBarController>().tabIndex.value,
onTap: Get.find<NavigationBarController>().changeTabIndex,
items: [
_bottomNavigationBarItem(
icon: CupertinoIcons.home,
label: 'Button1',
),
_bottomNavigationBarItem(
icon: CupertinoIcons.rocket_fill,
label: 'Button2',
),
])),
getPages: [
GetPage(
name: '/widget1',
page: () => Widget1(),
binding: Widget1_Bindings(),
),
GetPage(
name: '/widget2',
page: () => Widget2(),
binding: Widget2_Bindings(),
),
],
debugShowCheckedModeBanner: false,
themeMode: ThemeMode.system,
);
}
}
class NavigationBarController extends GetxController {
static NavigationBarController get to => Get.find();
var tabIndex = 0.obs;
void changeTabIndex(int index) {
tabIndex.value = index;
update();
}
@override
void onInit() {
super.onInit();
}
@override
void dispose() {
super.dispose();
}
}
class Controller1 extends GetxController {
var _test2 = "test1".obs;
get test1 => this._test2.value;
}
class Controller2 extends GetxController {
var _test2 = "test2".obs;
get test1 => this._test2.value;
}
class Widget1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Text("Widget1"),
);
}
}
class HomeBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => NavigationBarController());
}
}
class Widget1_Bindings extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => Controller1());
}
}
class Widget2_Bindings extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => Controller2());
}
}
class Widget2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Text("Widget2"),
);
}
}
_bottomNavigationBarItem({required IconData icon, required String label}) {
return BottomNavigationBarItem(
icon: Icon(icon),
label: label,
);
}
代码有两个问题。第一个是我收到错误:
第二个是我无法弄清楚如何获得 GetX 路由,例如:Get.to
工作。
你这里有一些问题。
首先,您在 GetMaterialApp
中定义了 initialRoute
和 home
,它们是两个不同的目的地。使用一个或另一个,而不是两个。
您正在将 NavigationBarController
绑定到您的 initialRoute
中定义的内容,但该应用试图转到您在 home
属性。因此该绑定永远不会被调用,这就是控制器未找到错误的原因。
由于您的 NavigationBarController
基本上是全局需要的,而不是逐页需要,因此我将失去绑定并在 运行 之前在 main
中初始化它应用程序。
void main() {
Get.put(NavigationBarController());
runApp(MyApp());
}
其次,如果您正在使用来自 GetX
class 的可观察变量,并且您希望 UI 发生变化,则需要将其包装在Obx
或 GetX
小部件。因此,将您的 BottomNavigationBar
包装在 Obx
.
中
bottomNavigationBar: Obx(
() => BottomNavigationBar(
currentIndex: Get.find<NavigationBarController>().tabIndex.value,
onTap: Get.find<NavigationBarController>().changeTabIndex,
items: [
_bottomNavigationBarItem(
icon: CupertinoIcons.home,
label: 'Button1',
),
_bottomNavigationBarItem(
icon: CupertinoIcons.rocket_fill,
label: 'Button2',
),
],
),
),
你的 IndexedStack
也一样。它需要包装在 Obx
中以根据 tabIndex
.
的更改重建
Obx(
() => IndexedStack(
index: Get.find<NavigationBarController>().tabIndex.value,
children: [Widget1(), Widget2()],
),
),
现在您的 BottomNavigationBar
可以工作了。至于 bindings
,因为您的应用是基于选项卡而不是导航到完整页面,所以您永远不必手动导航到带有 Get.to(() => Widget1());
的页面,这种情况下 Bindings
可以派上用场,但对于这种情况,我认为使用它们没有任何好处。我只会在每个选项卡中初始化控制器。所以总的来说它看起来像这样。我摆脱了 getPages
也是因为它们没有被使用。
void main() {
Get.put(NavigationBarController());
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
home: HomePage(),
debugShowCheckedModeBanner: false,
themeMode: ThemeMode.system,
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Demo"),
),
body: SafeArea(
child: Obx(
() => IndexedStack(
index: Get.find<NavigationBarController>().tabIndex.value,
children: [Widget1(), Widget2()],
),
),
),
bottomNavigationBar: Obx(
() => BottomNavigationBar(
currentIndex: Get.find<NavigationBarController>().tabIndex.value,
onTap: Get.find<NavigationBarController>().changeTabIndex,
items: [
_bottomNavigationBarItem(
icon: CupertinoIcons.home,
label: 'Button1',
),
_bottomNavigationBarItem(
icon: CupertinoIcons.rocket_fill,
label: 'Button2',
),
],
),
),
);
}
}
class NavigationBarController extends GetxController {
static NavigationBarController get to => Get.find();
var tabIndex = 0.obs;
final widgetList = <Widget>[Widget1(), Widget2()];
void changeTabIndex(int index) {
tabIndex.value = index;
// update(); don't need this, only if you're using GetBuilder
}
@override
void onInit() {
super.onInit();
}
@override
void dispose() {
super.dispose();
}
}
class Controller1 extends GetxController {
var _test2 = "test1".obs;
get test1 => this._test2.value;
}
class Controller2 extends GetxController {
var _test2 = "test2".obs;
get test1 => this._test2.value;
}
class Widget1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final controller = Get.put(Controller1());
return Center(
child: Container(
child: Obx(() => Text(controller.test1)),
),
);
}
}
class Widget2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final controller = Get.put(Controller2());
return Center(
child: Container(
child: Obx(() => Text(controller.test1)),
),
);
}
}
_bottomNavigationBarItem({required IconData icon, required String label}) {
return BottomNavigationBarItem(
icon: Icon(icon),
label: label,
);
}
此外,如果是我,我会对所有内容使用 GetBuilder
而不是可观察的流,因为您没有做任何真正证明流合理的事情。它们都有效,但 GetBuilder
是性能最高的选项。
更新:
在评论中回答您的问题:不,您不需要 IndexedStack
。
您可以传入给定索引处的小部件列表,当索引更改时 Obx
重建。关于 const 构造函数的说明与此无关,但您应该尽可能做。
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
final _widgetList = const <Widget>[
Widget1(),
Widget2()
]; // add const constructors to both these widgets
@override
Widget build(BuildContext context) {
final controller = Get.find<NavigationBarController>();
return Scaffold(
appBar: AppBar(
title: Text("Demo"),
),
body: SafeArea(
child: Obx(
() => Center(
child: _widgetList[controller.tabIndex.value], // or _widgetList.elementAt(controller.tabIndex.value)
),
),
),
...
原因 : 当Get.find() 在Get.put(Controller) 之前调用时发生。
在初始化 Get.put() 之前调用 Get.find() 显示错误
解决方案 :您可以简单地将 Get.put(controller) 调用到您的主 class 中,如下所示。那么来自任何 class 的 Get.find() 就会得到它。
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final YourController controller = Get.put(YourController());
...
@override
Widget build(BuildContext context) {
return MaterialApp(
......
}
注意:虽然有很多方法可以解决。
我正在尝试使用下一个布局创建简单的应用程序:
按钮应该切换 Widget1\Widget2。
我写了下一个代码(复制过去):
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:get/get_core/src/get_main.dart';
import 'package:get/get.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
initialBinding: HomeBinding(),
initialRoute: '/widget1',
home: Scaffold(
appBar: AppBar(
title: Text("Demo"),
),
body: SafeArea(
child: IndexedStack(
index: Get.find<NavigationBarController>().tabIndex.value,
children: [
Widget1(),
Widget2()
],
),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: Get.find<NavigationBarController>().tabIndex.value,
onTap: Get.find<NavigationBarController>().changeTabIndex,
items: [
_bottomNavigationBarItem(
icon: CupertinoIcons.home,
label: 'Button1',
),
_bottomNavigationBarItem(
icon: CupertinoIcons.rocket_fill,
label: 'Button2',
),
])),
getPages: [
GetPage(
name: '/widget1',
page: () => Widget1(),
binding: Widget1_Bindings(),
),
GetPage(
name: '/widget2',
page: () => Widget2(),
binding: Widget2_Bindings(),
),
],
debugShowCheckedModeBanner: false,
themeMode: ThemeMode.system,
);
}
}
class NavigationBarController extends GetxController {
static NavigationBarController get to => Get.find();
var tabIndex = 0.obs;
void changeTabIndex(int index) {
tabIndex.value = index;
update();
}
@override
void onInit() {
super.onInit();
}
@override
void dispose() {
super.dispose();
}
}
class Controller1 extends GetxController {
var _test2 = "test1".obs;
get test1 => this._test2.value;
}
class Controller2 extends GetxController {
var _test2 = "test2".obs;
get test1 => this._test2.value;
}
class Widget1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Text("Widget1"),
);
}
}
class HomeBinding extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => NavigationBarController());
}
}
class Widget1_Bindings extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => Controller1());
}
}
class Widget2_Bindings extends Bindings {
@override
void dependencies() {
Get.lazyPut(() => Controller2());
}
}
class Widget2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Text("Widget2"),
);
}
}
_bottomNavigationBarItem({required IconData icon, required String label}) {
return BottomNavigationBarItem(
icon: Icon(icon),
label: label,
);
}
代码有两个问题。第一个是我收到错误:
第二个是我无法弄清楚如何获得 GetX 路由,例如:Get.to
工作。
你这里有一些问题。
首先,您在 GetMaterialApp
中定义了 initialRoute
和 home
,它们是两个不同的目的地。使用一个或另一个,而不是两个。
您正在将 NavigationBarController
绑定到您的 initialRoute
中定义的内容,但该应用试图转到您在 home
属性。因此该绑定永远不会被调用,这就是控制器未找到错误的原因。
由于您的 NavigationBarController
基本上是全局需要的,而不是逐页需要,因此我将失去绑定并在 运行 之前在 main
中初始化它应用程序。
void main() {
Get.put(NavigationBarController());
runApp(MyApp());
}
其次,如果您正在使用来自 GetX
class 的可观察变量,并且您希望 UI 发生变化,则需要将其包装在Obx
或 GetX
小部件。因此,将您的 BottomNavigationBar
包装在 Obx
.
bottomNavigationBar: Obx(
() => BottomNavigationBar(
currentIndex: Get.find<NavigationBarController>().tabIndex.value,
onTap: Get.find<NavigationBarController>().changeTabIndex,
items: [
_bottomNavigationBarItem(
icon: CupertinoIcons.home,
label: 'Button1',
),
_bottomNavigationBarItem(
icon: CupertinoIcons.rocket_fill,
label: 'Button2',
),
],
),
),
你的 IndexedStack
也一样。它需要包装在 Obx
中以根据 tabIndex
.
Obx(
() => IndexedStack(
index: Get.find<NavigationBarController>().tabIndex.value,
children: [Widget1(), Widget2()],
),
),
现在您的 BottomNavigationBar
可以工作了。至于 bindings
,因为您的应用是基于选项卡而不是导航到完整页面,所以您永远不必手动导航到带有 Get.to(() => Widget1());
的页面,这种情况下 Bindings
可以派上用场,但对于这种情况,我认为使用它们没有任何好处。我只会在每个选项卡中初始化控制器。所以总的来说它看起来像这样。我摆脱了 getPages
也是因为它们没有被使用。
void main() {
Get.put(NavigationBarController());
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GetMaterialApp(
home: HomePage(),
debugShowCheckedModeBanner: false,
themeMode: ThemeMode.system,
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Demo"),
),
body: SafeArea(
child: Obx(
() => IndexedStack(
index: Get.find<NavigationBarController>().tabIndex.value,
children: [Widget1(), Widget2()],
),
),
),
bottomNavigationBar: Obx(
() => BottomNavigationBar(
currentIndex: Get.find<NavigationBarController>().tabIndex.value,
onTap: Get.find<NavigationBarController>().changeTabIndex,
items: [
_bottomNavigationBarItem(
icon: CupertinoIcons.home,
label: 'Button1',
),
_bottomNavigationBarItem(
icon: CupertinoIcons.rocket_fill,
label: 'Button2',
),
],
),
),
);
}
}
class NavigationBarController extends GetxController {
static NavigationBarController get to => Get.find();
var tabIndex = 0.obs;
final widgetList = <Widget>[Widget1(), Widget2()];
void changeTabIndex(int index) {
tabIndex.value = index;
// update(); don't need this, only if you're using GetBuilder
}
@override
void onInit() {
super.onInit();
}
@override
void dispose() {
super.dispose();
}
}
class Controller1 extends GetxController {
var _test2 = "test1".obs;
get test1 => this._test2.value;
}
class Controller2 extends GetxController {
var _test2 = "test2".obs;
get test1 => this._test2.value;
}
class Widget1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final controller = Get.put(Controller1());
return Center(
child: Container(
child: Obx(() => Text(controller.test1)),
),
);
}
}
class Widget2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
final controller = Get.put(Controller2());
return Center(
child: Container(
child: Obx(() => Text(controller.test1)),
),
);
}
}
_bottomNavigationBarItem({required IconData icon, required String label}) {
return BottomNavigationBarItem(
icon: Icon(icon),
label: label,
);
}
此外,如果是我,我会对所有内容使用 GetBuilder
而不是可观察的流,因为您没有做任何真正证明流合理的事情。它们都有效,但 GetBuilder
是性能最高的选项。
更新:
在评论中回答您的问题:不,您不需要 IndexedStack
。
您可以传入给定索引处的小部件列表,当索引更改时 Obx
重建。关于 const 构造函数的说明与此无关,但您应该尽可能做。
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
final _widgetList = const <Widget>[
Widget1(),
Widget2()
]; // add const constructors to both these widgets
@override
Widget build(BuildContext context) {
final controller = Get.find<NavigationBarController>();
return Scaffold(
appBar: AppBar(
title: Text("Demo"),
),
body: SafeArea(
child: Obx(
() => Center(
child: _widgetList[controller.tabIndex.value], // or _widgetList.elementAt(controller.tabIndex.value)
),
),
),
...
原因 : 当Get.find() 在Get.put(Controller) 之前调用时发生。 在初始化 Get.put() 之前调用 Get.find() 显示错误
解决方案 :您可以简单地将 Get.put(controller) 调用到您的主 class 中,如下所示。那么来自任何 class 的 Get.find() 就会得到它。
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final YourController controller = Get.put(YourController());
...
@override
Widget build(BuildContext context) {
return MaterialApp(
......
}
注意:虽然有很多方法可以解决。