I have this global bindings class to initialise some services and I need it to be initialised straight away:
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);
}
}
Which is in my 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,
);
}
}
Then in a class constructor I try to "find" it:
class UserLocalRepository extends VpService implements IUserLocalRepository {
UserLocalRepository() {
localDataSource = Get.find<LocalDataSource>();
}
LocalDataSource localDataSource;
And get this error:
══════ 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
...
════════════════════════════════════════════════════════════════════════════════
This is the binding mentioned in the error message:
class LoggedOutNickNameBinding extends Bindings {
LoggedOutNickNameBinding() {
_repository = Get.put(UserLocalRepository());
}
IUserLocalRepository _repository;
@override
void dependencies() {
Get.lazyPut<LoggedOutNickNameController>(
() => LoggedOutNickNameController(_repository),
);
}
}
Why are the "initialBindings" not initialised so that my app can "find" them when the app starts up?
About Get. GetX is an extra-light and powerful solution for Flutter. It combines high-performance state management, intelligent dependency injection, and route management quickly and practically.
The default way of creating a binding is by creating a class that implements Bindings. But alternatively, you can use BindingsBuilder callback so that you can simply use a function to instantiate whatever you desire.
Move Get. put from being a field of MainScreen to inside its build() method. The Controller can then be disposed when MainScreen is popped.
I'm guessing that there's a timing / ordering mismatch with when your GlobalBindings.dependencies() method gets called and when you need those resources.
You could try initializing your Bindings class prior to GetMaterialApp instead of passing your Bindings class to GetMaterialApp.
void main() async {
//WidgetsFlutterBinding.ensureInitialized(); // uncomment if needed for resource initialization
GlobalBindings().dependencies();
runApp(MyApp());
}
Just guessing here, but are some of the classes you're initializing via Get.put are slow-startup (i.e. async) before they are ready to use?
If so you could use
Get.putAsync<YourClass>(() async {
// init YourClass here
return await YourClass.slowInit();
}
I recently ran an exercise of performing async Bindings initialization prior to app being loaded for user interaction. Here's the code:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
enum Version {
lazy,
wait
}
// Cmd-line args/Env vars: https://stackoverflow.com/a/64686348/2301224
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;
}
}
In My case ::::
TestCartController? cartController;
if(condition){
cartController = Get.isRegistered<TestCartController>()
? Get.find<TestCartController>()
: Get.put(TestCartController());
}
but in some other widget I was referring to above controller as
final cartController = Get.find<TestCartController>();
Type mismatch issue coz both instances are different so it was causing problem for me. I simply removed that ? mark and it worked.
TestCartController cartController;
if(condition){
cartController = Get.isRegistered<TestCartController>()
? Get.find<TestCartController>()
: Get.put(TestCartController());
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With