I am using GetX. I need to display the data from database one the application open. But i get the Exception.
The following LateError was thrown building Obx(has builder, dirty, state: _ObxState#17527): LateInitializationError: Field 'products' has not been initialized.
Although, I have initialize the late variable inside onInit.
The Controller Code Is:
class HomeController extends GetxController {
HomeController({required this.homeRepository});
final IHomeRepository homeRepository;
late Rx<Either<FireStoreServerFailures, List<Product>>> products; //=
@override
void onInit() async {
products.value= await fetchProductsFromDB();
super.onInit();
}
Future<Either<FireStoreServerFailures, List<Product>>> fetchProductsFromDB() async {
var _completer=Completer<Either<FireStoreServerFailures, List<Product>>>();
homeRepository.fetchProducts().listen((event) {
_completer.complete(event);
});
return await _completer.future;
}
}
Home Page Where I Am Used The Late Variable's Code Is:
Obx(
() => GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 2 / 2,
),
// TODO Deal with errors
itemCount: controller.products.value.getOrElse(() => []).length,
itemBuilder: (context, index) {
return controller.products.value.fold(
(l) => Container(
height: double.infinity,
width: double.infinity,
color: Colors.red,
child: Text("Error ${l.msg}"),
),
(r) => Card(
elevation: 2.0,
color: Colors.amber,
child: InkWell(
onTap: () async =>
await controller.goToMoreDetails(),
child: Stack(
fit: StackFit.expand,
clipBehavior: Clip.hardEdge,
children: [
Image.network(
controller.products.value.fold(
(l) => "",
(r) => r[index]
.pickedImages
.getOrCrash()[0]),
fit: BoxFit.fill,
height: 200,
width: 200,
),
OverflowBox(
minHeight: 30,
alignment: Alignment.bottomCenter,
child: Container(
color: Colors.black.withOpacity(0.7),
height: 30,
width: double.infinity,
child: Center(
child: Text(
"${controller.products.value.fold((l) => "", (r) => r[index].price.getOrCrash())}",
style: const TextStyle(
color: Colors.white,
),
),
),
),
),
],
),
),
)) ;
}),
);
You declared late Rx<Either<FireStoreServerFailures, List<Product>>> products;
but did not initialise products
anywhere. But on your onInit
method you tried to access .value
on products
which is not yet initialised. Setting products.value
is not initialising products
. Also, your Obx
widget tries to access the products
field which is not initialised by the time it tries to access.
What you should do is:
final products = Rxn<Either<FireStoreServerFailures, List<Product>>>();
And in your UI:
Obx(
() => controller.products.value == null? CircularProgressIndicator() : GridView.builder(......