Flutter bool name = String its possible? - flutter

Hey i make a Favorite System with a bool to say if is favorite or not.
But if the name of the bool is always the same it applies to all my entries!
but each entry has its own name (widget.name), and i thought maybe something like that could work
bool widget.name;
but this not work :(
how can i solve that each entry has its own bool?
by the way i use this plugin for that
https://pub.dev/packages/shared_preferences/example
SharedPreferences sharedPreferences;
bool isfavorit;
#override
void initState() {
super.initState();
SharedPreferences.getInstance().then((SharedPreferences sp) {
sharedPreferences = sp;
isfavorit = sharedPreferences.getBool(spKey);
// will be null if never previously saved
if (isfavorit == null) {
isfavorit = false;
persist(isfavorit); // set an initial value
}
setState(() {});
});
}
void persist(bool value) {
setState(() {
isfavorit = value;
});
sharedPreferences?.setBool(spKey, value);
}
Complete Code
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Details extends StatefulWidget {
final String name;
Details(
this.name,
);
#override
_DetailsState createState() => _DetailsState();
}
const String spKey = 'myBool';
class _DetailsState extends State<Details> {
SharedPreferences sharedPreferences;
bool isfavorit;
#override
void initState() {
super.initState();
SharedPreferences.getInstance().then((SharedPreferences sp) {
sharedPreferences = sp;
isfavorit = sharedPreferences.getBool(spKey);
// will be null if never previously saved
if (isfavorit == null) {
isfavorit = false;
persist(isfavorit); // set an initial value
}
setState(() {});
});
}
void persist(bool value) {
setState(() {
isfavorit = value;
});
sharedPreferences?.setBool(spKey, value);
}
// ignore: missing_return
IconData favicon() {
if (isfavorit == true) {
return Icons.favorite;
} else if (isfavorit == false) {
return Icons.favorite_border;
}
}
// ignore: missing_return
Color favicolor() {
if (isfavorit == true) {
return Colors.red;
} else if (isfavorit == false) {
return Colors.white;
}
}
void changefav() {
if (isfavorit == true) {
return persist(false);
} else if (isfavorit == false) {
return persist(true);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
IconButton(
icon: Icon(
favicon(),
color: favicolor(),
),
onPressed: () => changefav(),
),
],
title: Text(widget.name),
),
body: Container(
child: Text(widget.name),
),
);
}
}

You are always saving the isFavorite to the same key in shared preferences, instead of using a constant key use one that is based on the widget.name
So for instance:
sharedPreferences.getBool('details_favorite_${widget.name}');

Related

Show flutter overlay according to different variables

I have a flutter screen called TestMain which has a scaffold and white background. The scaffolds body is supposed to change if certain events happen. The events are stored as a boolean. There is "isLocked" and "isPaused" which get emitted by a Riverpod Stream Provider and "isCheating" which changes when Applifecyle events get triggered. All of the three booleans are stored as Riverpod StateProviders, because of its global accesibility.
This is is my "isCheatingProvider":
final isCheatingProvider = StateProvider.autoDispose<bool>((ref) => false);
The "isPausedProvider" and "isLockedProvider" are the same.
This is the TestMain screen
class TestMain extends ConsumerStatefulWidget {
const TestMain({super.key});
#override
ConsumerState<TestMain> createState() => _TestMainScreenState();
}
class _TestMainScreenState extends ConsumerState<TestMain>
with WidgetsBindingObserver {
#override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
#override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) async {
super.didChangeAppLifecycleState(state);
final isCheating = ref.watch(isCheatingProvider.notifier);
switch (state) {
case AppLifecycleState.resumed:
case AppLifecycleState.inactive:
await sendCheatingAttempt(ref);
setState(() {
isCheating.state = true;
});
break;
case AppLifecycleState.paused:
await sendCheatingAttempt(ref);
setState(() {
isCheating.state = true;
});
break;
case AppLifecycleState.detached:
await sendCheatingAttempt(ref);
setState(() {
isCheating.state = true;
});
break;
}
}
#override
Widget build(BuildContext context) {
final List<Item> items = ref.watch(itemsProvider);
final AsyncValue<dynamic> wsTestListenerMessage =
ref.watch(testListenerProvider);
final isLocked = ref.watch(isLockedProvider.notifier);
final isPaused = ref.watch(isPausedProvider.notifier);
final isCheating = ref.watch(isCheatingProvider.notifier);
wsTestListenerMessage.when(
loading: () => {},
error: (err, stack) => print('Test State Error: $err'),
data: (message) async {
Future.delayed(const Duration(seconds: 0), () {
if (message["lock"] == true) {
isLocked.state = true;
}
if (message["unlock"] == true) {
isLocked.state = false;
}
if (message["paused"] == true) {
isPaused.state = true;
}
if (message["resumed"] == true) {
isPaused.state = false;
}
});
},
);
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: isPaused.state
? const ErrorOverlay(text: 'paused')
: isLocked.state || isCheating.state
? const ErrorOverlay(text: 'cheating')
: const TestView()),
);
}
}
But it doesnt work. No matter what I do. I added the Future.delayed(const Duration(seconds: 0), () {} around the if-statements, because it complained about changing the provider in build method, I use setState() in didChangeAppLifecycleState(), but can't use it in the listener, because the listener would called over and over again. It shouldnt be openend more than once.
(ErrorOverlay is a custom widget that just shows the text in big red letters, in the center)
remove the setState, this will do nothing
for set a state use ref.read(provider.notifier).state
for watch use ref.watch(isCheatingProvider)
By changing all that it is good by testing on my side :
final isCheatingProvider = StateProvider.autoDispose<bool>((ref) => false);
class TestMain extends ConsumerStatefulWidget {
const TestMain({key});
#override
ConsumerState<TestMain> createState() => _TestMainScreenState();
}
class _TestMainScreenState extends ConsumerState<TestMain>
with WidgetsBindingObserver {
#override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
#override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
#override
void didChangeAppLifecycleState(AppLifecycleState state) async {
super.didChangeAppLifecycleState(state);
final isCheating = ref.read(isCheatingProvider.notifier);
switch (state) {
case AppLifecycleState.resumed:
case AppLifecycleState.inactive:
isCheating.state = true;
break;
case AppLifecycleState.paused:
isCheating.state = true;
break;
case AppLifecycleState.detached:
isCheating.state = true;
break;
}
}
#override
Widget build(BuildContext context) {
final isCheating = ref.watch(isCheatingProvider);
return Scaffold(
backgroundColor: isCheating ? Colors.red : Colors.white,
body: SafeArea(
child: isCheating ? Text('cheat') : Text(' good')
)
);
}
}
You are incorrectly using StateProvider. To watch StateNotifier you should use
final isCheating = ref.watch(isCheatingProvider);
and to change provider use
ref.read(productSortTypeProvider.notifier).state = value;
So you have to change all provider related code.
#override
void didChangeAppLifecycleState(AppLifecycleState state) async {
super.didChangeAppLifecycleState(state);
final isCheatingNotifier = ref.read(isCheatingProvider.notifier);
switch (state) {
case AppLifecycleState.resumed:
case AppLifecycleState.inactive:
await sendCheatingAttempt(ref);
isCheatingNotifier.state = true;
break;
case AppLifecycleState.paused:
await sendCheatingAttempt(ref);
isCheatingNotifier.state = true;
break;
case AppLifecycleState.detached:
await sendCheatingAttempt(ref);
isCheatingNotifier.state = true;
break;
}
}
#override
Widget build(BuildContext context) {
final List<Item> items = ref.watch(itemsProvider);
final AsyncValue<dynamic> wsTestListenerMessage =
ref.watch(testListenerProvider);
final isLocked = ref.watch(isLockedProvider);
final isPaused = ref.watch(isPausedProvider);
final isCheating = ref.watch(isCheatingProvider);
wsTestListenerMessage.when(
loading: () => {},
error: (err, stack) => print('Test State Error: $err'),
data: (message) async {
Future.delayed(const Duration(seconds: 0), () {
final isLockedNotifier = ref.read(isLockedProvider.notifier);
final isPausedNotifier = ref.read(isPausedProvider.notifier);
if (message["lock"] == true) {
isLockedNotifier.state = true;
}
if (message["unlock"] == true) {
isLockedNotifier.state = false;
}
if (message["paused"] == true) {
isPausedNotifier.state = true;
}
if (message["resumed"] == true) {
isPausedNotifier.state = false;
}
});
},
);
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: isPaused
? const ErrorOverlay(text: 'paused')
: isLocked || isCheating
? const ErrorOverlay(text: 'cheating')
: const TestView()),
);
}

Infinite scroll loading Pagination problem in ListView Flutter

Problem with displaying images in ListView, have error app crash when load all images at once and pagination code i have now is not work for some reason
Basicly want to fetch images from this firebase colection and display them in 'ListView' with pagination to my app not crash.
Hopfuly somebody can help me fix this issue, thank you!
initSliderImages() async {
var result = await FirebaseFirestore.instance.collection('galerytab1');
result.snapshots().listen((data) {
List imgs = [];
data.docChanges.forEach((change) {
var imageData = change.doc.data();
String image = imageData?['url'];
imgs.add(CachedNetworkImage(imageUrl: image));
});
setState(() {
images = imgs;
});
});
}
class _CategoryTab1State extends State<CategoryTab1> {
List images = [];
late ScrollController controller;
final scaffoldKey = GlobalKey<ScaffoldState>();
#override
void initState() {
super.initState();
// addUrls();
controller = ScrollController()..addListener(_scrollListener);
initSliderImages();
if (this.mounted) {
context.read<CategoryTab1Bloc>().data.isNotEmpty
? print('data already loaded')
: context.read<CategoryTab1Bloc>().getData(mounted, widget.category);
}
}
#override
void dispose() {
controller.removeListener(_scrollListener);
super.dispose();
}
void _scrollListener() {
print(controller.position.extentAfter);
if (controller.position.extentAfter < 2) {
setState(() {
print('add 2 more');
print('add 2 more');
print('add 2 more');
print('add 2 more');
// images.addAll(['item1','item2','item3']
// List.generate(2, (index) => 'Inserted $index'
// )
// );
});
}
}
// //
// void addUrls() {
// final List<String> imgs = List.generate(
// 16,
// (_) {
// int random = Random().nextInt(16) + 16; // 250-500
// return
// // initSliderImages();
// // 'https://picsum.photos/$random/$random';
// 'https://firebasestorage.googleapis.com/v0/b/klosterkatz-c914e.appspot.com/o/galerytab1%2F1.png?alt=media&token=5b0e9c74-ec5a-42ca-aa59-309f41938a28';
//
//
//
//
// },
// );
// setState(() {
// images.addAll(imgs);
// });
// }
//
// Fetch images from databse for list
initSliderImages() async {
final int _limit = 3;
var result = await FirebaseFirestore.instance.collection('galerytab1');
result.snapshots().listen((data) {
List imgs = [];
data.docChanges.forEach((change) {
var imageData = change.doc.data();
String image = imageData?['url'];
imgs.add(image);
});
setState(() {
images = imgs;
});
});
}
#override
Widget build(BuildContext context) {
print('imagesimageimagesimagesimageismageimage');
print('$images');
print(images.length);
return NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification notification) {
if (notification.metrics.pixels ==
notification.metrics.maxScrollExtent) {
initSliderImages();
_scrollListener();
// addUrls();
}
return true;
},
child:
ListView.builder(
controller: controller,
key: widget.key,
itemCount: images.length,
itemExtent: 250,
itemBuilder: (context, index) {
return CachedNetworkImage(
imageUrl: images[index],
fit: BoxFit.cover,
key: ValueKey(images[index]),
);
}
),
);
}
}
In listview.Builder add shrinkWrap : primary false if not true
App is crashing due to memory issue. Following code is for proper pagination using firestore. Hope it will help you.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
class CategoryTab1 extends StatefulWidget {
const CategoryTab1({Key? key}) : super(key: key);
#override
State<CategoryTab1> createState() => _CategoryTab1State();
}
class _CategoryTab1State extends State<CategoryTab1> {
final _controller = ScrollController();
var _images = <String>[];
/// Flag for first time loading
var _isLoading = true;
/// Flag for paginated loading
var _isSubLoading = false;
/// last snapshot reference for pagination
QueryDocumentSnapshot<Map<String, dynamic>>? _lastSnapshot;
/// length of last images fetched
var _length = 10;
/// can load more if length is equal or more than 10
/// if less than 10 it means all images have been fetched
bool get _canLoadMore => _length >= 10;
#override
void initState() {
super.initState();
_loadData();
_controller.addListener(_listener);
}
#override
void dispose() {
_controller.removeListener(_listener);
_controller.dispose();
super.dispose();
}
void _listener() {
if (!_canLoadMore) {
return;
}
if (_isSubLoading || _isLoading) {
return;
}
if (_controller.position.extentAfter <= 0) {
_loadData();
}
}
final _collection = FirebaseFirestore.instance.collection('galerytab1');
void _loadData() async {
try {
if (_lastSnapshot != null) {
_isSubLoading = true;
setState(() {});
}
late QuerySnapshot<Map<String, dynamic>> _result;
/// Fetching images
if (_lastSnapshot == null) {
/// First time loading
_result = await _collection.limit(10).get();
} else {
/// Paginated loading
_result = await _collection
.startAfterDocument(_lastSnapshot!)
.limit(10)
.get();
}
final docs = _result.docs;
_length = docs.length;
for (final doc in docs) {
String im = doc.data()['url'] ?? '';
if (im.isNotEmpty) _images.add(im);
}
if (docs.isNotEmpty) _lastSnapshot = docs.last;
} catch (_) {}
_isLoading = false;
_isSubLoading = false;
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
child: ListView.builder(
controller: _controller,
itemCount: _images.length,
addAutomaticKeepAlives: true,
itemBuilder: (context, index) {
return CachedNetworkImage(
imageUrl: _images[index],
fit: BoxFit.cover,
key: ValueKey(_images[index]),
);
},
),
),
if (_isSubLoading) CircularProgressIndicator(),
],
),
);
}
}

Read data from Flutter via Bluetooth

I am trying to get the data from my bluetooth device. My problem is with the Flutter code to get such data.
services/sensor.dart
import 'dart:async';
import 'dart:convert' show utf8;
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:minertti/main.dart';
class SensorPage extends StatefulWidget {
const SensorPage({Key? key, required this.device}) : super(key: key);
final BluetoothDevice device;
#override
_SensorPageState createState() => _SensorPageState();
}
class _SensorPageState extends State<SensorPage> {
String service_uuid = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E";
String charaCteristic_uuid = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E";
late bool isReady;
late Stream<List<int>> stream;
late List _temphumidata;
double _charge = 0;
double _data_1 = 0;
double _data_2 = 0;
#override
void initState() {
super.initState();
super.initState();
isReady = false;
connectToDevice();
}
void dispose() {
widget.device.disconnect();
super.dispose();
}
connectToDevice() async {
if (widget.device == null) {
_pop();
return;
}
new Timer(const Duration(seconds: 15), () {
if (!isReady) {
disconnectFromDevice();
_pop();
}
});
await widget.device.connect();
discoverServices();
}
disconnectFromDevice() {
if (widget.device == null) {
_pop();
return;
}
widget.device.disconnect();
}
discoverServices() async {
if (widget.device == null) {
_pop();
return;
}
List<BluetoothService> services = await widget.device.discoverServices();
services.forEach((service) {
if (service.uuid.toString().isNotEmpty) {
service.characteristics.forEach((characteristic) {
if (characteristic.uuid.toString().isNotEmpty) {
characteristic.setNotifyValue(!characteristic.isNotifying);
stream = characteristic.value;
setState(() {
isReady = true;
});
}
});
}
});
if (!isReady) {
_pop();
}
}
_pop() {
Navigator.of(context).pop(true);
}
String _dataParser(List<int> dataFromDevice) {
return utf8.decode(dataFromDevice);
}
#override
Widget build(BuildContext context) {
return Scaffold(
// appBar: AppBar(
// title: Text('dht11 Sensor'),
// ),
body: Container(
child: !isReady
? Center(
child: Text(
"Waiting...",
style: TextStyle(
fontSize: 24, color: Color.fromARGB(255, 0, 0, 0)),
),
)
: Container(
child: StreamBuilder<List<int>>(
stream: stream,
builder: (BuildContext context,
AsyncSnapshot<List<int>> snapshot) {
if (snapshot.hasError)
return Text('Error: ${snapshot.error}');
if (snapshot.connectionState == ConnectionState.active) {
var data = snapshot.data as List<int>;
var currentValue = _dataParser(data);
print("REALDATA: $data");
_temphumidata = currentValue.split(",");
//_charge = double.parse('${_temphumidata[0]}');
//_data_1 = double.parse('${_temphumidata[1]}');
//_data_2 = _temphumidata[2];
return DeviceScreen1(
device: widget.device,
//charge: _charge,
//data_2: _data_2,
//data_1: _data_1,
charge: 90,
data_1: "Data 1",
data_2: "Data 2");
} else {
return Text('Check the stream');
}
},
),
)),
);
}
}
var data = snapshot.data as List;
var currentValue = _dataParser(data);
They do not show values. But, from my Arduino I know that it does send/notify data. That is, my problem is with reading and obtaining said data.

how to change the state inside FutureBuilder

i just need when the user open the screen the notification icon button change when he click, it's value is coming from shared preferences. the problem is the icon is never changed!
the initState code:
#override
void initState() {
super.initState();
_isActiveNotification = _notificationGetState();
}
_notificationGetState function is:
//getting notification on/off
Future<bool> _notificationGetState() async {
final SharedPreferences _prefs = await SharedPreferences.getInstance();
return _prefs.getBool('notification') ?? true;
}
_isActiveNotification variable is:
late Future<bool> _isActiveNotification;
the class of the notification icon button is:
class _NoificationActivationButton extends StatefulWidget {
_NoificationActivationButton();
#override
_NoificationActivationButtonState createState() =>
_NoificationActivationButtonState();
}
class _NoificationActivationButtonState
extends State<_NoificationActivationButton> {
#override
Widget build(BuildContext context) {
return FutureBuilder<bool>(
//function haveing the return value
future: _isActiveNotification,
builder: (context, snapshot) {
bool data = snapshot.data!;
return IconButton(
icon: Icon(
data
? Icons.notifications_active_outlined
: Icons.notifications_off_outlined,
color: Colors.white,
size: 40,
),
onPressed: () {
setState(() {
data = !data;
});
},
);
});
}
just call setstate
onPressed: () {
data = !data;
// just call setstate((){});
},
Make data a global state.
NOTE: I'm only assuming that you will only call _notificationGetState once (in initState).
Sample...
class _NoificationActivationButtonState
extends State<_NoificationActivationButton> {
final bool _isOtherVersion = true;
late Future<bool> _isActiveNotification;
bool? _data;
#override
void initState() {
super.initState();
_isActiveNotification = _notificationGetState();
}
//getting notification on/off
Future<bool> _notificationGetState() async {
final SharedPreferences _prefs = await SharedPreferences.getInstance();
return _isOtherVersion
? _prefs.getBool('notification') ?? true
: _data = _prefs.getBool('notification') ?? true;
}
#override
Widget build(BuildContext context) {
return FutureBuilder<bool>(
//function haveing the return value
future: _isActiveNotification,
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return const CircularProgressIndicator();
}
if (_isOtherVersion && _data == null) {
_data = snapshot.data;
}
return IconButton(
icon: Icon(
_data!
? Icons.notifications_active_outlined
: Icons.notifications_off_outlined,
color: Colors.white,
size: 40,
),
onPressed: () => setState(() => _data = !_data!),
);
},
);
}
}

Flutter Error when changing DropDownButton Selection

Error:
Failed assertion: line 609 pos 15: 'items == null ||
I/flutter (24295): items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) => item.value ==
I/flutter (24295): value).length == 1': is not true.
I did some research and did not figure out what caused the problem. Here is my code:
class StatusList extends StatefulWidget {
#override
_StatusListState createState() => _StatusListState();
}
class _DispositionListState extends State<DispositionList> {
var _currentSelectedValue = '';
Future<RecordList> recordList;
#override
void initState() {
recordList = getRecord();
super.initState();
}
int i = 1;
List<String> statusList = List<String>();
#override
Widget build(BuildContext context) {
return FutureBuilder<RecordList>(
future: recordList,
builder: (context, snapshot) {
if (snapshot.hasData) {
String current = snapshot.data.record[0].status.trim();
statusList.add(snapshot.data.record[0].status.trim());
while (i < snapshot.data.record.length) {
if (snapshot.data.record[i].status.trim() != current) {
statusList.add(snapshot.data.record[i].status.trim());
current = snapshot.data.record[i].status.trim();
}
i++;
}
_currentSelectedValue = statusList[0]; //not set this will straight getting error
return DropdownButton(
items: statusList.map((String dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: SizedBox(
width: 200.0,
child: Text(
dropDownStringItem,
overflow: TextOverflow.ellipsis,
),
));
}).toList(),
onChanged: (String valueSelected) {
onDropDownSelected(valueSelected);
},
value: _currentSelectedValue,
);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
});
}
void onDropDownSelected(String valueSelected) {
setState(() {
this._currentSelectedValue = valueSelected;
});
}
}
I tried compare the recordList and the valueSelected in onDropDownSelected return true. Problem caused when the setState is called even without any code inside. Anyone idea of what caused the problem based on these code?
Added code: Here is my getRecord()
Future<RecordList> getRecord() async {
String url = 'some url';
final response = await http.get(url, headers: {"Accept": "application/json"});
if (response.statusCode == 200) {
return RecordList.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load post');
}
}
class Record {
final String status;
final String disposition;
final int total;
Record({this.status, this.disposition, this.total});
factory Record.fromJson(Map<String, dynamic> json) {
return Record(
status: json['status'],
disposition: json['disposition'],
total: json['total']);
}
}
class RecordList {
final List<Record> record;
RecordList({this.record});
factory RecordList.fromJson(List<dynamic> parsedJson) {
List<Record> record = new List<Record>();
record = parsedJson.map((i) => Record.fromJson(i)).toList();
return new RecordList(
record: record,
);
}
}
It can be that the value property of DropdownButton has the value which is not one of item's value. value property should be either null or one of the item's value.
Also, maybe you don't need a FutureBuilder here. You can do something like that:
class _DispositionListState extends State<DispositionList> {
bool _isLoading = true;
String _currentSelectedValue;
List<String> statusList = List<String>();
#override
void initState() {
super.initState();
_loadStatusList();
}
_loadStatusList() async {
final recordList = await getRecord();
final list = recordList.record.map((r) {
return r.status.trim();
}).toSet().toList();
setState(() {
statusList = list;
_currentSelectedValue = list.first;
_isLoading = false;
});
}
#override
Widget build(BuildContext context) {
return isLoading ? CircularProgressIndicator() : _buildDropdown();
}
Widget _buildDropdown() {
return DropdownButton(
items: statusList.map((dropDownStringItem) {
return DropdownMenuItem<String>(
value: dropDownStringItem,
child: SizedBox(
width: 200.0,
child: Text(
dropDownStringItem,
overflow: TextOverflow.ellipsis,
),
),
);
}).toList(),
onChanged: (valueSelected) {
onDropDownSelected(valueSelected);
},
value: _currentSelectedValue,
);
}
void onDropDownSelected(String valueSelected) {
setState(() {
this._currentSelectedValue = valueSelected;
});
}
}
Update: Added .toSet() to filter out duplicates from statusList
I think the problem is that the status list has duplicated items. I added .toSet() before .toList() to filter out duplicates. Set is a collection of objects in which each object can occur only once.