找不到 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 中定义了 initialRoutehome,它们是两个不同的目的地。使用一个或另一个,而不是两个。

您正在将 NavigationBarController 绑定到您的 initialRoute 中定义的内容,但该应用试图转到您在 home 属性。因此该绑定永远不会被调用,这就是控制器未找到错误的原因。

由于您的 NavigationBarController 基本上是全局需要的,而不是逐页需要,因此我将失去绑定并在 运行 之前在 main 中初始化它应用程序。

void main() {
  Get.put(NavigationBarController());
  runApp(MyApp());
}

其次,如果您正在使用来自 GetX class 的可观察变量,并且您希望 UI 发生变化,则需要将其包装在ObxGetX 小部件。因此,将您的 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(
    ......
  
}

注意:虽然有很多方法可以解决。