I assign the onValue to two variables in initState.
_boc.selectList(locationId).then((onValue) {
list = onValue;
filterList = onValue;
setState(() {});
});
When it comes to this function, I clear the filterList, but the length of the list become 0.
Future<List<Obk>> getSuggestion(
String search) async {
if (search == "empty") return [];
if (search == "error") throw Error();
filterList.clear();
print(list.length); // this print 0
});
...
}
but if I remove this line filterList = onValue; , it will show the length of the list.
How to prevent the items in list from deleted?
Instead of assigned the same List Object to both list and filteredList. You can make a new list object using List.from(). So that your original List remains unchanged.
_boc.selectList(locationId).then((onValue) {
list = onValue;
filterList = List.from(onValue);
setState(() {});
});
Now if you try to run your code and print the list length then you'll not get 0 after calling filterList.clear().
Future<List<Obk>> getSuggestion(
String search) async {
if (search == "empty") return [];
if (search == "error") throw Error();
filterList.clear();
print(list.length); // this will print list length
});
...
}
Related
I have a Futurebuilder that fetches data from an Api.
I am assigning its data to a list;
List<TicketModel> ticketList = [];`
ticketList = snapshot.data;
Now the weird thing is, snapshot.data and ticketList should be independent right?
However if I remove data from the List e.g I remove every Object that has the price 1 the snapshot.data modifies too(Has same data as list now).
Why is that so?
The Futurebuilder is in a Modal bottom sheet if that's necessary
void main() {
List<String> listofAllTickets =[];
listofAllTickets = ["ticket eins","ticket zwei", "ticket drei"];
List<String> listOfAllTicketsSecond = listofAllTickets;
listOfAllTicketsSecond.removeWhere((element) => element == "ticket eins");
print(listofAllTickets);
print(listOfAllTicketsSecond);
}
you need to use a futurebuilder and connect ticketlist to it. the futurebuilder will generate a snapshot in its callback function. you can not access the snapshot outside of the futurebuilder.
I prefer using Bloc and streambuilder. Streambuilder events occur when change occurs on the notification stream.
As #Jeppe posted in the comments what I did before was that:
void main() {
List<String> listofAllTickets =[];
listofAllTickets = ["ticket eins","ticket zwei", "ticket drei"];
List<String> listOfAllTicketsSecond = listofAllTickets;
listOfAllTicketsSecond.removeWhere((element) => element == "ticket eins");
print(listofAllTickets);
print(listOfAllTicketsSecond);
}
the right solution would be doing this:
void main() {
List listofAllTickets = ["ticket eins","ticket zwei", "ticket drei"];
List listOfAllTicketsSecond = [];
listOfAllTicketsSecond = List.from(listofAllTickets);
listOfAllTicketsSecond.removeWhere((element) => element == "ticket eins");
print(listofAllTickets);
print(listOfAllTicketsSecond);
}
In Example two I am copying the data instead of referencing the list.
For each article the user browses, I want to save the ID information.
I am using getstorage my code sample is below.
I can not find a true way also, i am looking best way to save id's list.
final box = GetStorage();
List<String> myFavoriteList = [];
saveFav(String id) {
myFavoriteList.add(id);
box.write('favoriteArticles', myFavoriteList.cast<String>());
}
ifExistInFav(String id) async {
bool ifExists = false;
List<String> my = (box.read('favoriteArticles').cast<String>() ?? []);
ifExists = my.contains(id) ? true : false;
return ifExists;
}
First, you need to define your list and convert it to String.
** note that if you use a custom data type ensure you convert your model to String.
then you can use the following to store a List as a String object
final box = GetStorage('AppNameStorage');
/// write a storage key's value
saveListWithGetStorage(String storageKey, List<dynamic> storageValue) async => await box.write(/*key:*/ storageKey, /*value:*/ jsonEncode(storageValue));
/// read from storage
readWithGetStorage(String storageKey) => box.read(storageKey);
the saving procee implemention:
saveList(List<dynamic> listNeedToSave) {
/// getting all saved data
String oldSavedData = GetStorageServices().readWithGetStorage('saveList');
/// in case there is saved data
if(oldSavedData != null){
/// create a holder list for the old data
List<dynamic> oldSavedList = jsonDecode(oldSavedData);
/// append the new list to saved one
oldSavedList.addAll(listNeedToSave);
/// save the new collection
return GetStorageServices().saveListWithGetStorage('saveList', oldSavedList);
} else{
/// in case of there is no saved data -- add the new list to storage
return GetStorageServices().saveListWithGetStorage('saveList', listNeedToSave);
}
}
/// read from the storage
readList() => GetStorageServices().readWithGetStorage('saveList');
then the usage:
onTap: () async => debugPrint('\n\n\n read list items ${jsonDecode(await readList())}\n\n\n', wrapWidth: 800),
I have 2 List as I code here.
List<Detail> orderDetailList = List();
List<List> allOrders = List();
var result;
String tmpCustomerName;
My data came from my database as json, and here is some of my code.
await Dio().get(myURL).then((value) async {result = json.decode(value.data)});
for (var item in result) {
OrdersDetailModel ordersDetailModel = OrdersDetailModel.fromJson(item);
setState(() {
orders.add(ordersDetailModel);
customerName = ordersDetailModel.customerName;
customerPhone = ordersDetailModel.customerPhone;
var res2 = json.decode(ordersDetailModel.orderDetail);
for (var item2 in res2) {
Detail detail = Detail.fromJson(item2);
orderDetailList.add(detail);
}
allOrders.add(orderDetailList);
print('before $allOrders');
if (tmpCustomerName != customerName) {
orderDetailList.clear();
print('after $allOrders');
}
tmpCustomerName = customerName;
});
}
As I mentioned in my question part, when I use orderDetailList.clear() after added it to allOrders, the value in allOrders is gone too so allOrders has only empty list, as you can see I printed 'before' and 'after', the 'before' has value but 'after' does not. What am I doing wrong? Or how can I keep the value inside my allOrders list after clearing orderDetailList list?
This is the clear case of referencing error, you are doing. There is a concept called Shallow and Deep copy.
Shallow: It copies the item, but has some reference of the parent item. So when made any changes to either of them make changes in the other item. Which you are doing right now
Deep Copy: This is the copy method, where there is no reference to the parent variable. Which we have to do
So, let us quickly jump in the code:
// rather than doing add directly from orderDetailsList
// we add the data to the tempList holding the Details list,
// and then add it to the data
for (var item2 in res2) {
Detail detail = Detail.fromJson(item2);
orderDetailList.add(detail);
}
// this will keep the data into the list
List<Detail> tempList = [];
// traversing the item from orderDetailsList
orderDetailList.forEach((item) => tempList.add(item));
// here you add the tempList now holding the data
allOrders.add(tempList);
Read about List.forEach(). It will give you some concept clarity about the method.
I tried to edit a list in-place but wasn't able to get it working. Now trying to edit individual elements and add them to a second list. However the second list remains null and does not get updated. Any help would be appreciated.
var localFiles: MutableList<String> = File(localPath).list().toMutableList()
var localFileDates: MutableList<String>? = null
val iterateLocal = localFileDates?.listIterator()
for (item in localFiles) {
var date = item.takeLast(10).take(6)
if (date.matches("[0-9]+".toRegex()) and (date.length == 6) and (date != null) and (date != "null")) {
iterateLocal?.add(item.takeLast(10).take(6))
}
}
println(networkFiles) // prints correct outpu
println(localFileDates) // prints null
You need init localFileDates variable:
var localFileDates = MutableList()
var localFiles: MutableList<String> = File(localPath).list().toMutableList()
var localFileDates = MutableList<String>()
val iterateLocal = localFileDates?.listIterator()
for (item in localFiles) {
var date = item.takeLast(10).take(6)
if (date.matches("[0-9]+".toRegex()) and (date.length == 6) and (date != null) and (date != "null")) {
iterateLocal?.add(item.takeLast(10).take(6))
}
}
println(networkFiles) // prints correct outpu
println(localFileDates) // prints correct
It is better to use map{..} function to create a copy of the list with updated values.
val localFiles = File(localPath).list()?.toMutableList() ?: listOf()
val localFileDates = localFiles.mapNotNull { item ->
val date = item.takeLast(10).take(6)
if (date.matches("[0-9]{6}".toRegex()) {
date
} else {
null
}
}
println(localFiles)
println(localFileDates)
I use the mapNotNull{..} function calls the block for every element of the list and builds the new list only from non-null values.
You do not need var in your code, explicit type names can be omitted too.
The condition can be simplified - no need for the null check, the regular expression filters our the data == "null" case, the length check can be included into the regex too. The date variable can be re-used too.
A more idiomatic (and readable) way:
val localFileDates = File(localPath).list().map { it.takeLast(10).take(6) }.filter {
it.matches("[0-9]+".toRegex()) && (it.length == 6) && (it != "null")
}
Also I suggest you create a named function for takeLast(10).take(6) and the condition to make it clear what is the intent of these lines of code.
I have a list of data as key value pair say for example:
[0,"test"],
[1,"test1"],
[2,"test2"],
[0,"test5"],
[1,"test1"]
I just want to add this set of data into key-value pair as two individual set as follows
keyvaluepair1 =>[0,"test"],
[1,"test1"],
[2,"test2"],
keyvaluepair2 => [0,"test5"],
[1,"test1"]
If the pattern is that your key reverts to 0, then loop through the list and add a new dictionary to a list every time it resets.
//Your collection of KV Pair sets
var listOfKvs = new List<Dictionary<int,string>()
//an accumulator for the current set
var currentKvs = new Dictionary<int,string>()
var first = true;
foreach (var kv in keyvalues)
{
//The condition for when your key resets
if (kv.Key == 0)
{
if (first)
{
//we don't store the first dicitonary because it should be empty
first = false;
}
else
{
listOfKvs.Add(currentKvs);
}
currentKvs = new Dictionary<int, string>()
}
currentKvs.add(kv);
}
//Store the last dictionary
listOfKvs.add(currentKvs);