flutter add method was called on null using provider - flutter

Hello I want to add some value to my list. I have already googled for solutions but I can't see any other solutions besides initializing the list which I did.
When I try to add an item to my AutomaticDateList class I get the error:
The method 'add' was called on null.
Receiver: null
Tried calling: add(Instance of 'AutomaticDate')
Here is the class with the list in it.
class AutomaticDateList with ChangeNotifier {
List<AutomaticDate> items = []; // here I inialize
AutomaticDateList({this.items});
void addToList(AutomaticDate automaticDate) {
items.add(automaticDate);
notifyListeners();
}
List<AutomaticDate> get getItems => items;
}
This is the item I want to add to the list.
class AutomaticDate with ChangeNotifier {
String date;
String enterDate;
String leaveDate;
String place;
AutomaticDate({this.date, this.enterDate, this.leaveDate, this.place});
Here I call the method using the provider inside a page widget
void onGeofenceStatusChanged(Geofence geofence, GeofenceRadius geofenceRadius,
GeofenceStatus geofenceStatus) {
geofenceController.sink.add(geofence);
AutomaticDate automaticDateData = AutomaticDate();
automaticDateData.place = geofence.id;
automaticDateData.date = DateFormat("dd-mm-yyyy").format(DateTime.now());
if (geofenceStatus == GeofenceStatus.ENTER) {
widget.enterDate = DateFormat("HH:mm:ss").format(DateTime.now());
} else {
automaticDateData.leaveDate =
DateFormat("HH:mm:ss").format(DateTime.now());
automaticDateData.enterDate = widget.enterDate;
widget.list.add(automaticDateData);
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
AutomaticDateList automaticDateList =
Provider.of<AutomaticDateList>(context, listen: false);
automaticDateList.items.add(automaticDateData); // Here I add the data and get error "add was called on null"
print(automaticDateList.getItems);
});
}
}

The problem is in the initialization:
List<AutomaticDate> items = []; // here I inialize
AutomaticDateList({this.items});
You set a default value, but you are using the "auto-assign" sintax in the constructor, saying that items passing in the parameters are going to be assigned in the items property of the class.
You are instantiating the class using this code:
AutomaticDate automaticDateData = AutomaticDate();
So, you are passing "null" implicitly as parameter, then items [] got replaced with null value.
Just change the code to:
List<AutomaticDate> item;
AutomaticDateList({this.items = []}); // Default value

Related

Flutter pushed value in array still updating

I have a shopping cart project using provider. When changing variant(array of object) the already pushed value inside the cart also changes. How do I prevent the value from changing when it is already inserted.
Adding items to cart
addProduct() async{
final productDetailsProvider =Provider.of<ProductDetailsProvider>(context,listen: false);
List<VariantDetails>? variants = productDetailsProvider.variants;
List<AddOnDetails>? extras = productDetailsProvider.extras;
double total = productDetailsProvider.total;
CartData cartItem = CartData(
addOnList: extras,
variantList: variants,
total:total);
final cart =Provider.of<CartProvider>(context,listen: false);
cart.addToCart(context, cartItem);
}
Provider class - The cart array variantList still changes when clicking button again. Should not change for the already pushed/added values. Total does not change only variantList and extras
class CartProvider extends ChangeNotifier {
List<CartData>? cart = [];
addToCart(context,CartData cartItem) {
if (cart!.isEmpty) {
cart?.add(cartItem);
}
print('${cart?[0]?.variantList}');//variantList changes value even when it's already pushed to array
}
Provider class changing variant for reference
class ProductDetailsProvider extends ChangeNotifier {
List<VariantDetails>? variants = [];
addVariant(VariantDetails? item) {
var exist =
variants?.indexWhere((element) => element.typeID == item?.typeID);
if (exist != -1) {
variants?[exist!] = item!;
} else {
variants?.insert(0, item!);
}
}
}

objects are not stored into objectbox (Flutter)

So Im trying to save an object(with only one String attribute) in the ObjectBox. The ObjectBox is called favoriteBox. With the onLongPress-function im trying to put the object in the box. In the initState-function im trying to put all the objects (more specific: the string attributes of each object) in to a nested list.
My problem now is that after calling the onLongPress-function and putting the object in the favoriteBox, the favoritBox is null according to the Debugger.
Im not sure where my mistake is.
class _GridViewJokesState extends State<GridViewJokes> {
late int seasonsListIndex;
List<List<String?>> seasonsList = seasons;
final toast = FToast();
final AudioPlayer audioPlayer = AudioPlayer();
late SeasonProvider seasonProvider;
Store? _store;
Box<FavoritesEntity>? favoritesBox;
#override
void initState() {
super.initState();
toast.init(context);
getApplicationDocumentsDirectory().then((dir) {
_store = Store(getObjectBoxModel(), directory: dir.path + "/objectbox");
});
favoritesBox = _store?.box<FavoritesEntity>();
seasonsList[5] =
favoritesBox?.getAll().map((e) => e.quoteName).toList() ?? [];
}
void onLongPress(listTileIndex) {
if (seasonProvider.seasonPicked) {
seasonsList[5].add(seasonsList[seasonsListIndex][listTileIndex]);
favoritesBox?.put(FavoritesEntity(
quoteName: seasonsList[seasonsListIndex][listTileIndex]));
toast.showToast(
child: buildToast("Zu Favoriten hinzugefĆ¼gt"),
gravity: ToastGravity.BOTTOM);
}
import 'package:objectbox/objectbox.dart';
#Entity()
class FavoritesEntity {
FavoritesEntity({required this.quoteName});
int id = 0;
String? quoteName;
}
The issue is that the code does not await the Future that returns the application Documents directory before accessing store. So store will still be null and the following line that gets a box does nothing.
getApplicationDocumentsDirectory().then((dir) {
_store = Store(getObjectBoxModel(), directory: dir.path + "/objectbox");
});
// store is still null here:
favoritesBox = _store?.box<FavoritesEntity>();
You can either move the box get code into the then() closure. Or, as we recommend, init Store into a global variable using a helper class in the main function. See our examples.

Duplicate Array list value automatically changed in Flutter

I'm very surprised after this issue. First, inform all things I have used in my project.
I have used Getx in my project. I have called the API using the Getx controller file.
Below code used in getx controller file. "PLTimeSlotModel" is model and. it has two params (name, isselect).
var futureTimeSlot_PL_C_D = Future.value(<PLTimeSlotModel>[]).obs;
callTimeSlotAPI() async {
futureTimeSlot_PL_C_D.value = FetchTimeSlotList();
}
Future<List<PLTimeSlotModel>> FetchTimeSlotList() async {
// Fetching data with API calling
}
Screen A:
List<PLTimeSlotModel> listA = [];
List<PLTimeSlotModel> listB = [];
#override
void initState() {
super.initState();
_plController.callTimeSlotAPI();
}
Another method is to create two lists using the future list:
List<PLTimeSlotModel> temp1 = await _plController.futureTimeSlot_PL_C_D.value;
temp1.forEach((element) {
listA.add(element);
listB.add(element);
});
onclick:
for(int i =0;i<listA.length;i++){
listA[i].isselect = false;
print(listA[i].isselect);
print(listB[i].isselect);
}
Now the issue is I have changed/updated the only "listA" value, So why automatically set the same value to "listB"? The two list is based on the one list.
A List in Dart contains references objects, not the objects themselves. So what you are doing is copying references to objects into two lists. But since they are pointing at the same objects, you will see any modification in one list also happen in the other list. You need to copy each PLTimeSlotModel object and put the copy into your new list.
One way to copy objects is to create an constructor which takes an object of the same type and creates a new object based on this first object. So something like this:
class Person {
String name;
Person(this.name);
Person.fromPerson(Person other) : this(other.name);
#override
String toString() => 'Person($name)';
}
void main() {
final persons = [
Person('Adam'),
Person('Bob'),
];
// Make new list based on persons
final otherPersonList = [
...persons.map((person) => Person.fromPerson(person))
];
otherPersonList[0].name = 'Carl';
print(persons); // [Person(Adam), Person(Bob)]
print(otherPersonList); // [Person(Carl), Person(Bob)]
}

How to make model fields observable in Flutter

I have a model called category , which has two fields, User has a list of categories and what to update the category name, for State Management getx is used
class Category {
String? categoryName;
bool status;
Category(this.categoryName,this.status);
}
I have a observable list called catList which is used in List widget
var catList = <Category>[].obs;
when I update the category field it doest not update
catList[index].categoryName = categoryChangedName.value;
but If I update the item in object and then assign the object to catList then It changed
catList[index] = Category(categoryChangedName.value, catList[index].status );
My question is how to make model fields observable, if we have more fields changes then this is not proper way.
As of GetX documentation you need to update values using method and call update(); method inside custom object !
Ex:
class Controller extends GetxController {
int counter = 0;
void increment() {
counter++;
update(); // look here!
}
}
Your use case might be like....
class Category {
String? categoryName;
bool status;
Category(this.categoryName,this.status);
void updateCategoryName(name){
this.categoryName = name;
update();
}
}
//Use like..
catList[index].updateCaetgoryName = categoryChangedName.value;

flutter/dart static list or list of singleton object always return it's default values when calling it from another class

i am trying to use static list as global variable that can be accessible through all the dart classes , so i have done like that:
class MyData {
// initialize it to an empty list
static var List<MyObject> myObjectList = new List<MyObject>();
}
then in another class I load that empty list with list of MyObject (no doubt that it loaded with success)
I do add objects to that list , the list will not remain empty !!
when it comes the time to use the myObjectList in another class it returns an empty list with 0 length
class SomeClass {
.....
void getMyObjectsList(){
.....
// this display 0 length and has no data
print("my static object list length == ${MyData.myObjectList.length}");
}
}
i have also tried using a singleton instance and it return the same result :
class MyData {
static final MyData _singleton = MyData._internal();
factory MyData() {
return _singleton;
}
MyData._internal();
// object property
var List<MyObject> myObjectList = new List<MyObject>();
}
well this also return the default value which is an empty list:
class SomeClass {
.....
void getMyObjectsList(){
....
// this display 0 length and has no data
print("my singleton object list length == ${MyData().myObjectList.length}");
}
}
I think you missed to Store/Copy/Add objects in the List
class MyData {
// initialize it to an empty list
static List<MyObject> myObjectList = [];
}
Add some Objects to List before accessing the List
class SomeClass {
.....
/// Add Object to List using this Method
void addDataToList(MyObject data){
myObjectList.add(data);
}
void getMyObjectsList(){
.....
// this display 0 length and has no data
print("my static object list length == ${MyData.myObjectList.length}");
}
}
Note : if there is no Data list will return 0
so please add some data before using the .length() on List.
Hope this Solve your Issue
the problem was not in the static list , it was inside the TextField onTap event ,
i was using the static list inside it so i tried to use a local variable and i faced the same problem , the variable return the default value always.