Duplicate Array list value automatically changed in Flutter - 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)]
}

Related

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.

Dart list added to another list becomes empty when emptying the first list

I have the below user defined objects -
class PhoneBookContact {
String? phoneBookContact;
List<ContactNumber>? contactNumbers;
PhoneBookContact(this.phoneBookContact, this.contactNumbers);
}
class ContactNumber {
String phone;
bool availableOnBol;
ContactNumber(this.phone, this.availableOnBol);
}
In my main method I am creating a list for the ContactNumber class and then later adding that ContactNumber list to the contactNumbers property of PhoneBookContact list. This is all done inside of a for loop.
The issue I am having is when I am clearing the contactNumbers list after adding those items to the contactNumbers property of the PhoneBookContact list, I see those cleared from the PhoneBookContact list as well, which I find weird, or maybe I am not thinking it the right way.
List<PhoneBookContact> phoneBookContacts = [];
List<ContactNumber> contactNumbers = [];
for (var contact in contacts) {
contactNumbers.clear();
if (contact.phones.isNotEmpty) {
for (var phone in contact.phones) {
if (true) {
contactNumbers.add(ContactNumber(phone.number, true));
} else {
contactNumbers.add(ContactNumber(phone.number, false));
}
}
}
phoneBookContacts
.add(PhoneBookContact(contact.displayName, contactNumbers));
}
Your PhoneBookContact constructor does not make a copy of the list. It takes a reference to the list and remembers it.
Since you clear the list every loop but reuse the same list instance, all your PhoneBookContacts will have the same list.
Lets clean up your method a little:
List<PhoneBookContact> phoneBookContacts = [];
for (var contact in contacts) {
List<ContactNumber> contactNumbers = [];
for (var phone in contact.phones) {
final condition = true; // should be your complicated expression
contactNumbers.add(ContactNumber(phone.number, condition));
}
phoneBookContacts.add(PhoneBookContact(contact.displayName, contactNumbers));
}
Apart from removing some clutter, it makes sure that each loop, you instantiate a new list so that each PhoneBookContact has it's own list.

flutter add method was called on null using provider

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

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.

How to concatenate a class with a variable to get a static variable from this class?

I am making a pokemon app and I have a question that I already had in other projects and I would like to know if anyone can help me with a solution.
I receive a variable called pokemonName from other screen, I want to pass the variable and concatenate with the class "Strings", it will be like Strings.+pokemonName.toLowerCase(), converting to lowercase to get the map from the class Strings, but I don't know how to achieve this to remove the switch and don't need to use a lot of cases for each pokemon.
class PokemonDetailScreen extends StatelessWidget {
final String pokemonName;
final String image;
Map<String, dynamic> pokemonMap = {};
PokemonDetailScreen(this.pokemonName, this.image, this.index){
getPokemonMap();
}
#override
Widget build(BuildContext context) {
return Container();
}
void getPokemonMap(){
switch(pokemonName){
case "Bulbasaur":
pokemonMap = Strings.bulbasaur;
break;
case "Charmander":
pokemonMap = Strings.charmander;
break;
}
}
}
**Class in another dart file:**
class Strings {
static Map bulbasaur = {};
}
What I needed is something like this:
void getPokemonMap(){
pokemonMap = Strings.$pokemonMap.toLowerCase();
}
What you could do is have a static map indexed by the name of your Pokemons and whose values are maps.
class Strings {
static Map<String, dynamic> map = {
'Bulbasor': {},
'Charmander': {},
// ...
};
}
And you’ll use it like this: pokemonMap = Strings.map[pokemonName].
~You can use JSON file to do all this things instead use a class.~
I recommend not use a static class to do that thing, instead you can just make a normal class and instantiate on another file, so when the class that you call your another class will be dispose when the parent was.
class PokemonStrings {
Map bulbasaur = {your map here};
}
To call that in another file you need just do
PokemonString _pokemonString = PokemonString();
And call whatever you need in the class that you instantiate
var bulbasaurMap = _pokemonString.bulbasaur;
But even so you need walk with static class. Just call the name of class followed by dot to access all the static attributes
var bulbasaurMap = PokemonString.bulbasaur;