Flutter Getx - "Xxx" 未找到。您需要调用 "Get.put(Xxx())" - 但我调用了 Get.put(Xxx())
Flutter Getx - "Xxx" not found. You need to call "Get.put(Xxx())" - But i have called Get.put(Xxx())
我有这个全局绑定 class 来初始化一些服务,我需要立即初始化它:
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 构造函数中我尝试“找到”它:
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”没有初始化,以便我的应用程序可以在应用程序启动时“找到”它们?
我猜你的 GlobalBindings.dependencies() 方法被调用的时间和你需要这些资源的时间不匹配。
您可以尝试初始化您的绑定 class 先于 到 GetMaterialApp,而不是将您的绑定 class 传递给 GetMaterialApp.
void main() async {
//WidgetsFlutterBinding.ensureInitialized(); // uncomment if needed for resource initialization
GlobalBindings().dependencies();
runApp(MyApp());
}
切线
这里只是猜测,但是您通过 Get.put 初始化的某些 class 是否在准备好使用之前启动缓慢(即异步)?
如果是这样你可以使用
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:
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;
}
}
以我为例:::
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());
}
原因 : 当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(
......
}
我有这个全局绑定 class 来初始化一些服务,我需要立即初始化它:
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 构造函数中我尝试“找到”它:
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”没有初始化,以便我的应用程序可以在应用程序启动时“找到”它们?
我猜你的 GlobalBindings.dependencies() 方法被调用的时间和你需要这些资源的时间不匹配。
您可以尝试初始化您的绑定 class 先于 到 GetMaterialApp,而不是将您的绑定 class 传递给 GetMaterialApp.
void main() async {
//WidgetsFlutterBinding.ensureInitialized(); // uncomment if needed for resource initialization
GlobalBindings().dependencies();
runApp(MyApp());
}
切线
这里只是猜测,但是您通过 Get.put 初始化的某些 class 是否在准备好使用之前启动缓慢(即异步)?
如果是这样你可以使用
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:
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;
}
}
以我为例:::
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());
}
原因 : 当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(
......
}