How to save multiple bool from list in Flutter with SharedPreferences - list

I have created a bool List:
List<bool> switchbool = [true, true, true, true];
On change of a switch, the value change (pretty obvious...). But I would like to store those information exactly as they are in the list, because I use them like this:
Switch(
value: switchbool[index],
onChanged: (value) {
_saveBoolFromSharedPref(value, app[index]);
setState(() {
switchbool[index] = value;
});
},
)
But with this it doesn't load the true or false stored in the sharedPreferences that I saved:
Future<void> _getBoolFromSharedPref() async {
final prefs = await SharedPreferences.getInstance();
switchbool.length = app.length;
for (var i = 0; i < app.length; i += 1) {
final myBool = prefs.getBool(app[i]) ?? false;
}
}
And here is the _saveBoolFromSharedPref:
Future<bool> _saveBoolFromSharedPref(bool value, String appName) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(appName, value);
//print(switchbool);
}
Any advice will be wonderful, thanks a lot!
If I could maybe retrieve the data from the value field on the switch with a future void but I haven't seen anywhere any answer...

Maybe store your values in a map and then decode/encode them. Like following:
var jsn = prefs.getString('Map');
Map = json.decode(jsn);
var jsn = json.encode(Map);
prefs.setString('Map', jsn);
Let me know if it helps.

Try this for your _getBoolFromSharedPref method.
Future<void> _getBoolFromSharedPref() async {
final prefs = await SharedPreferences.getInstance();
switchbool.length = app.length;
for (var i = 0; i < app.length; i += 1) {
switchbool[i] = prefs.getBool(app[i]) ?? false;
}

Related

HandshakeException: Handshake error in client (OS Error: I/flutter ( 9113): CERTIFICATE_VERIFY_FAILED: Hostname mismatch(handshake.cc:359))

Connection code
till yesterday everything working properly but now it giving the error to connect the json data.
...........................................................................................................................................................................................
class ProductDataStacture with ChangeNotifier {
List<Products> _products = [];
List<Banners> _banners = [];
List<Categories> _category = [];
List<Random> _random = [];
Future<bool> getProducts() async {
String url = 'https://shymee.com';
try {
// http.Response response = await http.get(Uri.parse(url + "/home"),
var response = await http.get(Uri.parse(url + "/home"), headers: {
'Authorization': 'token a867c3c092e8b1195f398ed5ca52dda4e5ff5ed8'
});
var data = json.decode(response.body);
print(data);
List<Products> prod = [];
List<Banners> bann = [];
List<Categories> cate = [];
List<Random> ran = [];
data['products'].forEach((element) {
Products product = Products.fromJson(element);
prod.add(product);
print("this is product ${product}");
});
data['banners'].forEach((element) {
Banners banner = Banners.fromJson(element);
bann.add(banner);
});
data['categories'].forEach((element) {
Categories category = Categories.fromJson(element);
cate.add(category);
});
data['random'].forEach((element) {
Random random = Random.fromJson(element);
ran.add(random);
});
_products = prod;
_banners = bann;
_category = cate;
_random = ran;
return true;
} catch (e) {
print("e getProducts");
print(e);
return false;
}
}
List<Products> get productsList {
return [..._products];
}
List<Banners> get bannersList {
return [..._banners];
}
List<Categories> get categoryList {
return [..._category];
}
List<Random> get randomList {
return [..._random];
}
}
Temporary you can solve this issue with below recommend
class MyHttpOverrides extends HttpOverrides{
#override
HttpClient createHttpClient(SecurityContext? context){
return super.createHttpClient(context)
..badCertificateCallback = (X509Certificate cert, String host, int
port)=> true;
}
}
enter link description here
But my suggestion is you use valid certificate in server side

Add an another attribute to an existing List in Flutter

I have been trying many ways to add an isChecked: false attribute to every list inside the _filterOptions List in my Flutter Project. I couldn't find any solution to this. If there is any solution I am happy to see it.
List<dynamic> _filters = [];
List<List<dynamic>> _filterOptions =[];
var filters =
await json.decode(data)["getProductsByStore"]["aggregations"];
for(int i = 0; i < filters.length; i++){
_filters.add(filters[i]["label"]);
_filterOptions.add(filters[i]["options"]);
}
//print(filters[0]["options"]);
//print(_filters);
print(_filterOptions);
I am getting this kind of nested list when printed and I want to add the attribute to every list.
as an example:
[[{count: 3, label: 30-40, value: 30_40, isChecked:false}], [{count: 2, label: Bagged , value: 50, isChecked:false},{...},{...}...]]
Create Model class with your data and bool isChecked
class ModelClass{
String? label;
int? count;
List? options;
bool? isChecked;
ModelClass({this.label, this.count , this.options, this.isChecked = false});
ModelClass.fromJson(Map<String, dynamic> json){
label = json['label'];
count = json['count'];
options = json['options'];
}
}
then you can add data like below code
List<ModelClass> list = [];
void function()async{
List<dynamic> _filters = [];
List<List<dynamic>?> _filterOptions =[];
var filters =
await json.decode(data)["getProductsByStore"]["aggregations"];
for(int i = 0; i < filters.length; i++){
ModelClass modelClass = ModelClass.fromJson(filters[i]);
list.add(modelClass);
_filters.add(modelClass.label);
_filterOptions.add(modelClass.options);
}
print(list[0].options);
print(list[0].isChecked);
}
if you want to modify isChecked for some specific index
list[0].isChecked = false;
Just add these lines.
class YourWrapperClass {
YourWrapperClass({this.filterOptions = const [], this.isChecked = false});
List<List<dynamic>> filterOptions;
bool isChecked;
}
YourWrapperClass filterWrapper = YourWrapperClass(filterOptions: _filterOptions, isChecked: false);
And use this wrapper class object whenever ya need to access _filterOptions.
But, I would more rather recommend using the WrapperClass on the list elements, like so.
class YourWrapperClass {
YourWrapperClass({this.filterOption = const [], this.filter="", this.isChecked = false});
List<dynamic> filterOption;
dynamic filter;
bool isChecked;
}
List<YourWrapperClass> list = [];
var filters =
await json.decode(data)["getProductsByStore"]["aggregations"];
for(int i = 0; i < filters.length; i++){
list.add(YourWrapperClass(filterOption:filters[i]["options"], filter:filters[i]["label"], isChecked=false));
_filterOptions.add(filters[i]["options"]);
}

Setting up NSubstitute Mock for functions that implement asp.net core IMemoryCache

I have a function that returns a status like this:
public async Task<Result> UpdateWeight(string id, int weight)
{
var data = await service.GetData(id);
if (data != null)
{
var user = await GetInfo(data.UserId);
var changedWeight = await UpdateWeight(newWeight, user);
if (!changedWeight)
{
return new ChangeWeightResult("Weight not updated");
}
return new ChangeWeightResult(newWeight);
}
return new ChangeWeightResult("Error changing weight");
}
And I'm trying to set up a unit test (xUnit - NSubstitute) for it.
public async Task UpdateUserAvatar_WhenCalled_ReturnChangedAvatarSuccess()
{
//Arrange
var id = "id";
var newWeight = 30;
var data = new DataEntity
{
Id = id
};
var user = new User
{
UserId = "id"
};
service.GetData(Arg.Any<string>()).Returns(data);
service.GetUser(Arg.Any<string>()).Returns(user);
//Act
var result = await service.UpdateWeight(data.Id, newWeight;
//Assert
result.IsSuccessful.Should().BeTrue();
result.Weight.Should().Be(newWeight);
}
However I keep stumble upon error such as null for the memory cache (CacheEntryFake) when I don't return the User or
"Cannot return value of type Task 1 for IMemoryCache.CreateEntry"
These are all the functions that I called within the function that I want to test
public async Task<DataEntity> GetData(string id)
{
var data = await memoryCache.GetOrCreateAsync(id, CacheFactory);
return data;
}
internal async Task<DataEntity> CacheFactory(ICacheEntry cache)
{
var data = await GetDataFromDb(cache.Key.ToString());
if (IsExpiredSession(data))
{
cache.Dispose();
}
else
{
cache.SetAbsoluteExpiration(relative);
}
return data;
}
private async Task<bool> GetInfo(string id)
{
if(setting.CacheTimeout > 0)
{
return await
memoryCache.GetOrCreateAsync(id, InfoCacheFactory):
}
return id;
}

How to delete duplicates of a List<MyDataModel> (Dart/Flutter)

I have a futurebuilder that builds the UI based on a List, it does the job, however I get duplicates due to the UI being built again and again whenever I navigate. My question is, is there a innate method in Dart that can remove duplicates from a list? I've tried this StackOverflow question however it doesn't work.
Here is my custom model:
class HomeList {
Widget navigateScreen;
String imagePath;
PatientInfo patientInfo;
HomeList({
this.navigateScreen,
this.imagePath = '',
this.patientInfo,
});
static List<HomeList> homeList = [];
}
Here is my function for the futureBuilder i'm getting the data from my cloud_firestore:
_getPatients() async {
if (didLoadpatients == 0) {
print('this is didloadpatients at start of func $didLoadpatients');
var document = await db
.collection('users')
.document(mUser.uid)
.collection('patients');
document.getDocuments().then((QuerySnapshot query) async {
query.documents.forEach((f) {
uids.add(f.data['uID']);
});
didLoadpatients++;
print('this is didloadpatients at end of func $didLoadpatients');
for (var i = 0; i < uids.length; i++) {
var userDocuments = await db.collection('users').document(uids[i]);
userDocuments.get().then((DocumentSnapshot doc) {
print(doc.data);
homeList.add(HomeList(
imagePath: 'assets/fitness_app/fitness_app.png',
patientInfo: new PatientInfo.fromFbase(doc.data)));
});
print(homeList);
}
});
} else
print('I am leaving the get patient function');
}
Future<bool> getData() async {
_getCurrentUser();
await Future.delayed(const Duration(milliseconds: 1500), () async {
_getPatients();
});
return true;
}
Any help would be appreciated thank you!
To remove duplicates you can use Set Data Structure instead of List.
Just use Set instead of List to get unique values only.
Before Adding you can Remove Element from model this will Work
dummymodel.removeWhere((m) => m.id == id);
dummymodel.add(dummymodel.fromJson(data));
To Remove Duplicates from Data Model simply use Set (Data structure),
Original List with Duplicate Entries:
List<MyDataModel> mList = [MyDataModel(1), MyDataModel(2), MyDataModel(1), MyDataModel(3)];
New List that removes duplicate Entries from your List<MyDataModel>:
List<MyDataModel> mNewList = list.toSet().toList();
Output:
The result will be like
MyDataModel(1), MyDataModel(2), MyDataModel(3)
To remove the duplicate elements from custom object list, you need to override == and hashcode methods in your POJO class and then add the items in Set and again convert set to list to remove duplicate objects. Below is the working code:-
class TrackPointList {
double latitude;
double longitude;
String eventName;
Time timeZone;
TrackPointList({
this.latitude,
this.longitude,
this.eventName,
this.timeZone,
});
#override
bool operator==(other) {
// Dart ensures that operator== isn't called with null
// if(other == null) {
// return false;
// }
if(other is! TrackPointList) {
return false;
}
// ignore: test_types_in_equals
return eventName == (other as TrackPointList).eventName;
}
int _hashCode;
#override
int get hashCode {
if(_hashCode == null) {
_hashCode = eventName.hashCode;
}
return _hashCode;
}
factory TrackPointList.fromJson(Map<String, dynamic> json) => TrackPointList(
latitude: json["latitude"].toDouble(),
longitude: json["longitude"].toDouble(),
eventName: json["eventName"],
timeZone: timeValues.map[json["timeZone"]],
);
Map<String, dynamic> toJson() => {
"latitude": latitude,
"longitude": longitude,
"eventName": eventName,
"timeZone": timeValues.reverse[timeZone],
};
}
Above is the POJO class. Now below is the method which helps you to filter the objects according to the eventName data member.
List<TrackPointList> getFilteredList(List<TrackPointList> list){
final existing = Set<TrackPointList>();
final unique = list
.where((trackingPoint) => existing.add(trackingPoint))
.toList();
return unique;
}
This will work definitely.
Please +1 if it helps you.
I've come up with quite a brute force solution. Instead of
_getPatients() async {
if (didLoadpatients == 0) {
print('this is didloadpatients at start of func $didLoadpatients');
var document = await db
.collection('users')
.document(mUser.uid)
.collection('patients');
document.getDocuments().then((QuerySnapshot query) async {
query.documents.forEach((f) {
uids.add(f.data['uID']);
});
didLoadpatients++;
print('this is didloadpatients at end of func $didLoadpatients');
for (var i = 0; i < uids.length; i++) {
var userDocuments = await db.collection('users').document(uids[i]);
userDocuments.get().then((DocumentSnapshot doc) {
print(doc.data);
homeList.add(HomeList(
imagePath: 'assets/fitness_app/fitness_app.png',
patientInfo: new PatientInfo.fromFbase(doc.data)));
});
print(homeList);
}
});
} else
print('I am leaving the get patient function');
}
I've done what #Jay Mungara says and clear my Set everytime my UI rebuilds:
_getPatients() async {
homeList.clear();
if (didLoadpatients == 0) {
print('this is didloadpatients at start of func $didLoadpatients');
var document = await db
.collection('users')
.document(mUser.uid)
.collection('patients');
document.getDocuments().then((QuerySnapshot query) async {
query.documents.forEach((f) {
uids.add(f.data['uID']);
});
didLoadpatients++;
print('this is didloadpatients at end of func $didLoadpatients');
for (var i = 0; i < uids.length; i++) {
var userDocuments = await db.collection('users').document(uids[i]);
userDocuments.get().then((DocumentSnapshot doc) {
print(doc.data);
homeList.add(HomeList(
imagePath: 'assets/fitness_app/fitness_app.png',
patientInfo: new PatientInfo.fromFbase(doc.data)));
});
print(homeList);
}
});
} else
print('I am leaving the get patient function');
}
Thank you for all your answers!
this is a small examples to remove duplicate element
removeDuplicate() {
List<dynamic> demoList = [
{"userId": 1, "id": 1, "name": "thappu1"},
{"userId": 2, "id": 2, "name": "appu"},
{"userId": 1, "id": 1, "name": "thappu1"},
{"userId": 2, "id": 2, "name": "appu"},
{"userId": 2, "id": 2, "name": "appu"},
{"userId": 2, "id": 2, "name": "appu"},
{"userId": 2, "id": 2, "name": "appu"},
];
var toRemove = {};
demoList.forEach((e) {
toRemove.putIfAbsent("$e", () => e);
});
print(toRemove.keys.toList());
}
output is
[{userId: 1, id: 1, name: thappu1}, {userId: 2, id: 2, name: appu}]

My async call is returning before list is populated in forEach loop

I have a routine which gets a list of filenames from the device, then reads the file(s) to build a list. However, the calling routine always returns with zero items. I print the filenames, so I know they exist, however, it appears that the async is returning before I read the files. I used similar code when making an HTTP call. But, something here is causing the routine to return the list even though it hasn't completed. Perhaps, it is possible that I am calling it at the wrong time? I am calling retrieveItems here:
#override
void initState() {
super.initState();
retrieveItems();
}
Eventually I will have a refresh button, but for now I'd simply like the list to populate with the data from the files...
--------------------
Callee
Future<List<String>> readHeaderData() async {
List<String> l = new List();
List<String> files = await readHeaders(); // Gets filenames
files.forEach((filename) async {
final file = await File(filename);
String contents = await file.readAsString();
User usr = User.fromJson(json.decode(contents));
String name = usr.NameLast + ", " + usr.NameFirst;
print(name);
l.add(name);
}
return l;
Caller
void retrieveItems() async {
LocalStorage storage = new LocalStorage();
await storage.readHeaderData().then((item) {
try {
if ((item != null ) &&(item.length >= 1)) {
setState(() {
users.clear();
_users.addAll(item);
});
} else {
setState(() {
_users.clear();
final snackbar = new SnackBar(
content: new Text('No users found.'),
);
scaffoldKey.currentState.showSnackBar(snackbar);
});
}
} on FileNotFoundException catch (e) {
print(e.toString()); //For debug only
setState(() {
_users.clear();
});
});
}
});
This code
Future<List<String>> readHeaderData() async {
List<String> l = new List();
List<String> files = await readHeaders(); // Gets filenames
files.forEach((filename) async {
final file = await File(filename);
String contents = await file.readAsString();
User user = User.fromJson(json.decode(contents));
String name = user.NameLast + ", " + user.NameFirst;
print(name);
l.add(name);
}
return l;
}
returns the list l and then processes the asyc forEach(...) callbacks
If you change it to
Future<List<String>> readHeaderData() async {
List<String> l = new List();
List<String> files = await readHeaders(); // Gets filenames
for(var filename in files) { /// <<<<==== changed line
final file = await File(filename);
String contents = await file.readAsString();
User user = User.fromJson(json.decode(contents));
String name = user.NameLast + ", " + user.NameFirst;
print(name);
l.add(name);
}
return l;
}
the function will not return before all filenames are processed.
files.forEach((filename) async {
means that you can use await inside the callback, but forEach doesn't care about what (filename) async {...} returns.
Also possible
await Future.forEach(yourList, (T elem) async { ...async staff });
To expand on Günter's comment regarding using list.map(f), here's an example of converting a forEach call so that it works correctly.
Broken example
Incorrectly assumes forEach will wait on futures:
Future<void> brokenExample(List<String> someInput) async {
List<String> results;
someInput.forEach((input) async {
String result = await doSomethingAsync(input);
results.add(result);
});
return results;
}
Corrected example
Waits on the async functions to complete, using Future.wait and .map():
Future<void> correctedExample(List<String> someInput) async {
List<String> results;
await Future.wait(someInput.map((input) async {
String result = await doSomethingAsync(input);
results.add(result);
}));
return results;
}
I encountered the similar issue. The problem is that dart will NOT wait for "forEach" contrary to public believe. There are two solutions:
1) Convert forEach to for loop as indicated by others. Another is use Future:
2) await Future.forEach(list, (item) async {
// your code
final result = await getMyResult();
});
Another option
Future.wait(someList.map((item) => something_returns_future(item)));