Flutter Getx - 找不到 "Xxx"。你需要调用 "Get.put(Xxx())" - 但是我已经调用了 Get.put(Xxx())。

20
我有一个全局绑定类,用于初始化一些服务,我需要它立即初始化。
import 'package:get/get.dart';
import 'package:vepo/data/data_provider/local_data_provider.dart';
import 'package:vepo/data/data_source/local_data_source.dart';

import 'services/authentication_service.dart';

class GlobalBindings extends Bindings {
  final LocalDataProvider _localDataProvider = LocalDataProvider();
  @override
  void dependencies() {
    Get.put<AuthenticationService>(AuthenticationService(), permanent: true);
    Get.put<LocalDataProvider>(_localDataProvider, permanent: true);
    Get.put<LocalDataSource>(LocalDataSource(_localDataProvider),
        permanent: true);
  }
}

在我的initialBindings中的是哪个?
class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Vepo',
      initialRoute: AppPages.INITIAL,
      initialBinding: GlobalBindings(),
      transitionDuration: const Duration(milliseconds: 500),
      defaultTransition: Transition.rightToLeft,
      getPages: AppPages.routes,
      home: Root(),
      theme: homeTheme,
    );
  }
}

然后在一个类的构造函数中,我尝试“找到”它:
class UserLocalRepository extends VpService implements IUserLocalRepository {
  UserLocalRepository() {
    localDataSource = Get.find<LocalDataSource>();
  }

  LocalDataSource localDataSource;

我遇到了这个错误:
══════ Exception caught by widgets library ═══════════════════════════════════
The following message was thrown building App(dirty):
"LocalDataSource" not found. You need to call "Get.put(LocalDataSource())" or "Get.lazyPut(()=>LocalDataSource())"

The relevant error-causing widget was
App
lib/main.dart:17
When the exception was thrown, this was the stack
#0      GetInstance.find
package:get/…/src/get_instance.dart:272
#1      Inst.find
package:get/…/src/extension_instance.dart:66
#2      new UserLocalRepository
package:vepo/…/user/user_local_repository.dart:10
#3      new LoggedOutNickNameBinding
package:vepo/…/logged_out_nickname/logged_out_nick_name_binding.dart:11
#4      AppPages.routes
package:vepo/…/routes/app_pages.dart:29
...
════════════════════════════════════════════════════════════════════════════════

这是错误信息中提到的绑定。
class LoggedOutNickNameBinding extends Bindings {
  LoggedOutNickNameBinding() {
    _repository = Get.put(UserLocalRepository());
  }

  IUserLocalRepository _repository;

  @override
  void dependencies() {
    Get.lazyPut<LoggedOutNickNameController>(
      () => LoggedOutNickNameController(_repository),
    );
  }
}

为什么"initialBindings"没有被初始化,以至于我的应用程序在启动时无法"找到"它们?
7个回答

23

我猜想当你需要这些资源时,你的GlobalBindings.dependencies()方法被调用的时间或顺序不匹配。

你可以尝试在GetMaterialApp之前初始化你的Bindings类,而不是将你的Bindings类传递给GetMaterialApp。

void main() async {
  //WidgetsFlutterBinding.ensureInitialized(); // uncomment if needed for resource initialization
  GlobalBindings().dependencies();
  runApp(MyApp());
}

正切

只是猜测,你通过 Get.put 初始化的一些类在使用前是否需要慢启动(即异步)?

如果是这样,你可以使用

Get.putAsync<YourClass>(() async {
 // init YourClass here
 return await YourClass.slowInit();

}

示例

我最近进行了一个练习,即在用户与应用程序进行交互之前执行异步绑定初始化。这是代码:

import 'package:flutter/material.dart';
import 'package:get/get.dart';

enum Version {
  lazy,
  wait
}
// Cmd-line args/Env vars: https://dev59.com/B1QI5IYBdhLWcg3w7QHJ#64686348
const String version = String.fromEnvironment('VERSION');
const Version running = version == "lazy" ? Version.lazy : Version.wait;

void main() async {
  //WidgetsFlutterBinding.ensureInitialized(); // if needed for resources
  if (running == Version.lazy) {
    print('running LAZY version');
    LazyBindings().dependencies();
  }

  if (running == Version.wait) {
    print('running AWAIT version');
    await AwaitBindings().dependencies(); // await is key here
  }

  runApp(MyApp());
}

class LazyBindings extends Bindings {
  @override
  void dependencies() {
    Get.lazyPut<MyDbController>(() => MyDbController());
  }
}

/// Simulates a slow (2 sec.) init of a data access object.
/// Calling [await] dependencies(), your app will wait until dependencies are loaded.
class AwaitBindings extends Bindings {
  @override
  Future<void> dependencies() async {
    await Get.putAsync<MyDbController>(() async {
      Dao _dao = await Dao.createAsync();
      return MyDbController(myDao: _dao);
    });
  }
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final MyDbController dbc = Get.find();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('GetX Bindings'),
      ),
      body: Center(
        child: Obx(() => Text(dbc.dbItem.value)),
      ),
    );
  }
}

class MyDbController extends GetxController {
  Dao myDao;

  MyDbController({this.myDao});

  RxString dbItem = 'Awaiting data'.obs;

  @override
  void onInit() {
    super.onInit();
    initDao();
  }

  Future<void> initDao() async {
    // instantiate Dao only if null (i.e. not supplied in constructor)
    myDao ??= await Dao.createAsync();
    dbItem.value = myDao.dbValue;
  }
}

class Dao {
  String dbValue;

  Dao._privateConstructor();

  static Future<Dao> createAsync() async {
    var dao = Dao._privateConstructor();
    print('Dao.createAsync() called');
    return dao._initAsync();
  }

  /// Simulates a long-loading process such as remote DB connection or device
  /// file storage access.
  Future<Dao> _initAsync() async {
    dbValue = await Future.delayed(Duration(seconds: 2), () => 'Some DB data');
    print('Dao._initAsync done');
    return this;
  }
}


4
在我的情况下:
TestCartController? cartController;

if(condition){
 cartController = Get.isRegistered<TestCartController>()
            ? Get.find<TestCartController>()
            : Get.put(TestCartController());

}

但在我上面提到的其他小部件中,我将控制器称为

final cartController = Get.find<TestCartController>();

类型不匹配问题,因为它们是两个不同的实例,所以它给我带来了问题。我只需要去掉那个问号标记,就能让它正常工作。

TestCartController cartController;

if(condition){
 cartController = Get.isRegistered<TestCartController>()
            ? Get.find<TestCartController>()
            : Get.put(TestCartController());

}

2
Add fenix : true;

class AppBinding implements Bindings {
      @override
      void dependencies() {
        Get.lazyPut<GeneralController>(() => GeneralController(), fenix: true);
        Get.lazyPut<UserController>(() => UserController(), fenix: true);
      }
    }

这个会解决你的问题。

需要解释一下。例如,你改了什么?为什么改了它?为什么它有效?这个想法/要点是什么?来自帮助中心的解释是:“...始终解释为什么你提出的解决方案是合适的,以及它是如何工作的”。请通过编辑(更改)你的回答来回应,而不是在评论中回应(但是*** *** *** *** *** 不要 *** *** *** *** ***使用“编辑:”,“更新:”或类似的词语 - 回答应该看起来像是今天写的)。 - undefined
好的,那不会很快解封:“此账户因剽窃行为而被暂时停用。” - undefined

2

原因:当在初始化Get.put(Controller)之前调用Get.find()时,就会发生这种情况。在初始化Get.put()之前调用Get.find()会显示错误。

解决方法:只需将Get.put(controller)调用到您的主类中,如下所示。然后从任何类中调用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(
    ......
  
}

1
如果您的控制器类没有与任何“有状态/无状态”类绑定,那么您可以像这样在主方法中初始化控制器类。
Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // init app controller
  AppController appController =
  await Get.putAsync<AppController>(() async => AppController(), permanent: true);
  // init temp storage
  await GetStorage.init();
  runApp(const MyApp());
}

1
我遇到了这个错误,并且通过将Obx替换为GetX来解决了它。不再使用:
Obx(() => Text(controller.text)),

使用
GetX<MyController>(builder:(c) => Text(c.text)),

请注意,您应该使用GetX构建器控制器(c)而不是默认的控制器(controller)。

0

确保您的LocalDataSource继承并实现这些类。

LocalDataSource extends GetxController implements GetxService

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接