Cannot remove strings from list in flutter - flutter

I have a page to select images from the gallery and add those urls in a list that will be passed to another page after popping. Everything works fine the first time the user accesses the page, however, when coming back to the Image View with an already populated list (passed as argument), whenever I try to edit/removing elements from it, the list remains the same. But the images I want to delete get removed correctly from the firebase storage.
I will attach the code I am trying to use. I am new to flutter so I will really appreciate your help.
If you have any questions about the code feel free to ask!
import 'dart:convert';
import 'dart:io';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:moneybo/utilities/dialogs/delete_dialog.dart';
import 'package:moneybo/utilities/dialogs/error_dialog.dart';
import 'package:moneybo/utilities/generics/get_arguments.dart';
class ImageView extends StatefulWidget {
const ImageView({super.key});
#override
State<ImageView> createState() => _ImageViewState();
}
class _ImageViewState extends State<ImageView> {
late final ImagePicker _picker;
late final ImageCache _cache;
List<String> imageUrls = [];
List<bool> isImageSelected = [];
List<String> imagesToDelete = [];
String imgs = "";
bool _isSelected = false;
#override
void initState() {
_picker = ImagePicker();
_cache = ImageCache();
super.initState();
}
#override
Widget build(BuildContext context) {
List<String>? newImageList;
final imageList = context.getArgument<String>();
if (imageList != null && imageList.isNotEmpty) {
newImageList = (jsonDecode(imageList) as List<dynamic>).cast<String>();
for (String url in newImageList) {
if (!imageUrls.contains(url)) {
imageUrls.add(url);
}
}
imgs = jsonEncode(imageUrls);
for (String element in imageUrls) {
isImageSelected.add(false);
}
}
return GestureDetector(
onTap: () {
List<bool> newIsImageSelected = [];
for (String element in imageUrls) {
newIsImageSelected.add(false);
}
setState(() {
_isSelected = false;
isImageSelected = newIsImageSelected;
imagesToDelete = [];
});
print(imageUrls);
// print(imgs);
},
child: Scaffold(
appBar: AppBar(
centerTitle: true,
toolbarHeight: 73,
leading: Padding(
padding: const EdgeInsets.only(top: 25, left: 5),
child: TextButton(
child: const Text(
"OK",
style: TextStyle(fontSize: 18, color: Colors.white),
),
onPressed: () => Navigator.pop(context, imgs),
),
),
actions: [
Padding(
padding: const EdgeInsets.only(right: 20, top: 20),
child: isImageSelected.contains(true)
? IconButton(
onPressed: () async {
final shouldDelete = await showDeleteDialog(
context, "Delete this image(s)?");
if (shouldDelete) {
for (String deleteImage in imagesToDelete) {
imageUrls.removeWhere((image) =>
image.hashCode == deleteImage.hashCode);
await FirebaseStorage.instance
.refFromURL(deleteImage)
.delete();
}
imgs = jsonEncode(imageUrls);
List<bool> newIsImageSelected = [];
for (String element in imageUrls) {
newIsImageSelected.add(false);
}
_cache.clear();
_cache.clearLiveImages();
setState(() {
isImageSelected = newIsImageSelected;
imagesToDelete = [];
});
}
},
icon: SizedBox(
height: 25,
child: Image.asset(
"lib/icons/bin.png",
color: Colors.white,
)))
: IconButton(
icon: const Icon(Icons.add_a_photo_rounded),
onPressed: () async {
List<XFile>? images = await _picker.pickMultiImage();
String uniqueFileName =
DateTime.now().microsecondsSinceEpoch.toString();
Reference referenceRoot =
FirebaseStorage.instance.ref();
Reference referenceDirImages =
referenceRoot.child("images");
try {
for (XFile image in images) {
uniqueFileName =
(int.parse(uniqueFileName) + 1).toString();
Reference referenceImageToUpload =
referenceDirImages.child(uniqueFileName);
await referenceImageToUpload
.putFile(File(image.path));
String imageUrl =
await referenceImageToUpload.getDownloadURL();
imageUrls.add(imageUrl);
isImageSelected.add(false);
}
} catch (error) {
if (mounted) {
showErrorDialog(context, "$error");
}
}
imgs = jsonEncode(imageUrls);
setState(() {});
},
),
),
],
title: const Padding(
padding: EdgeInsets.only(top: 30.0),
child: Text(
"Add images",
style: TextStyle(fontSize: 16),
),
),
flexibleSpace: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: <Color>[
Color.fromRGBO(24, 92, 92, 1),
Color.fromRGBO(33, 108, 108, 1),
Color.fromRGBO(40, 121, 121, 1),
Color.fromRGBO(48, 136, 136, 1),
Color.fromRGBO(50, 139, 139, 1),
Color.fromRGBO(54, 143, 143, 1),
Color.fromRGBO(57, 145, 145, 1),
]),
),
),
),
body: imageUrls.isNotEmpty
? Padding(
padding: const EdgeInsets.only(top: 20, left: 8, right: 8),
child: GridView.builder(
itemCount: imageUrls.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: imageUrls.length > 1 ? 2 : 1,
mainAxisSpacing: imageUrls.isNotEmpty ? 8 : 0,
crossAxisSpacing: imageUrls.isNotEmpty ? 8 : 0,
),
itemBuilder: (context, index) {
return GestureDetector(
onLongPress: () {
setState(() {
_isSelected = true;
});
},
child: Container(
decoration: BoxDecoration(
border: Border.all(
color: _isSelected
? Colors.green
: const Color.fromRGBO(11, 68, 68, 1),
width: _isSelected ? 4 : 2),
borderRadius:
const BorderRadius.all(Radius.circular(20))),
child: Stack(
children: [
Center(
child: Image.network(
imageUrls[index],
fit: BoxFit.contain,
),
),
_isSelected
? Align(
alignment: Alignment.topRight,
child: Transform.scale(
scale: 1.3,
child: Checkbox(
side: const BorderSide(
width: 2,
color: Color.fromRGBO(
11, 68, 68, 1)),
shape: const CircleBorder(),
value: isImageSelected[index],
onChanged: (bool? value) {
setState(() {
isImageSelected[index] = value!;
});
if (isImageSelected[index]) {
if (imagesToDelete.isNotEmpty) {
imagesToDelete.insert(
index, imageUrls[index]);
} else {
imagesToDelete
.add(imageUrls[index]);
}
} else if (!isImageSelected[
index] &&
imagesToDelete.contains(
imageUrls[index])) {
imagesToDelete
.remove(imageUrls[index]);
} else {
return;
}
print(imagesToDelete);
}),
),
)
: const SizedBox(),
],
),
),
);
},
),
)
: Padding(
padding: const EdgeInsets.only(bottom: 150),
child: Center(
child: SizedBox(
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(
Icons.image_not_supported_outlined,
size: 150,
color: Color.fromRGBO(168, 168, 168, 1),
),
SizedBox(height: 25),
Text(
"No images yet",
style: TextStyle(
color: Color.fromRGBO(168, 168, 168, 1),
fontSize: 25,
),
)
]),
)),
),
),
);
}
}

Related

Looking up a deactivated widget's ancestor is unsafe.Flutter integaration test

type here
iam new to flutter and trying to learn test integration test package and i have come around this error.
The following assertion was thrown while finalizing the widget
tree:
Looking up a deactivated widget's ancestor is unsafe.
At this point the state of the widget's element tree is no longer
stable.
To safely refer to a widget's ancestor in its dispose() method,
save a reference to the ancestor by calling
dependOnInheritedWidgetOfExactType() in the widget's
didChangeDependencies() method.
and to the little understanding that i have this is the class throwing that error
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:modal_progress_hud/modal_progress_hud.dart';
import 'package:rflutter_alert/rflutter_alert.dart';
import 'package:wildai/helper/check_connectivity.dart';
import 'package:wildai/helper/common_methods.dart';
import 'package:wildai/helper/screen_config.dart';
import 'package:wildai/helper/toast_helper.dart';
import 'package:wildai/redux/actions.dart';
import 'package:wildai/redux/app_state.dart';
import 'package:wildai/redux/middleware/checkin_calls/checkin_update_get_data_call.dart';
import 'package:wildai/redux/middleware/homescreen_calls/update_single_view_calls.dart';
import 'package:wildai/src/models/dashboard/dashboard_model.dart';
import 'package:wildai/src/widgets/buttons/custom_radio_button.dart';
import 'package:wildai/src/widgets/custom_margins.dart';
import 'package:wildai/src/widgets/my_bottom_sheet.dart';
import 'package:wildai/utils/custom_alert.dart';
import 'package:wildai/utils/my_custom_text_theme.dart';
import 'package:wildai/helper/http_wrapper_custom.dart' as http;
import 'package:wildai/utils/my_redesign_icons.dart';
class EditCheckInOverlayPage extends StatefulWidget {
EditCheckInOverlayPage(this.title, this.avaiableCheckinItem,
this.updateCheckinsUrl, this.keyValue,
{Key key, this.showLoading = false, this.checkInRequestBody})
: super(key: key);
final String title;
final Map avaiableCheckinItem;
final String keyValue;
final String updateCheckinsUrl;
final Map checkInRequestBody;
bool showLoading;
\_EditCheckInOverlayPageState createState() =\> \_EditCheckInOverlayPageState();
}
class \_EditCheckInOverlayPageState extends State\<EditCheckInOverlayPage\> {
String micIconString = 'assets/icons/microphone.png';
Map responseBody = {'show_checkins': {}};
List\<AvaiableCheckinItemModel\> avaiableCheckinItems;
DateTime delayTime = DateTime.now();
final FlutterSecureStorage storage = new FlutterSecureStorage();
final store = StoreProvider.of\<AppState\>(SizeConfig.rootPagecOntext);
#override
void initState() {
super.initState();
avaiableCheckinItems = widget.avaiableCheckinItem\[widget.keyValue\];
List\<int\> requiredIntList = \[\];
for (var i = 0; i \< avaiableCheckinItems.length; i++) {
if (avaiableCheckinItems\[i\].require) {
requiredIntList.add(i);
}
}
for (int index in requiredIntList) {
var temp = avaiableCheckinItems\[index\];
avaiableCheckinItems.removeAt(index);
avaiableCheckinItems.insert(0, temp);
}
}
#override
void dispose() {
super.dispose();
if (mounted && !responseBody\['show_checkins'\].isEmpty) {
updateAvaiableCheckInsResponse();
print('///////////////////////////////');
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.transparent,
body: Align(
alignment: Alignment.bottomCenter,
child: MyBottomModelSheet.titleSheet(
title: 'Edit ${widget.title} Check-ins',
height: 530,
onClose: () {
Navigator.pop(context);
},
body: sortDetailsContainer()),
),
);
}
Widget titleWidget() {
return Container(
decoration: BoxDecoration(color: Colors.white, boxShadow: \[
BoxShadow(
blurRadius: 25,
color: SizeConfig.primaryTextColour.withOpacity(.3),
)
\]),
child: Row(
children: \[
Expanded(
child: Padding(
padding: cmargin(top: 31, left: 30, right: 30),
child: Text(
'Edit ${widget.title} Check-Ins'.toUpperCase(),
style: MyCustomTextStyles().buttonTextSmall.copyWith(
color: SizeConfig.primaryTextColour.withOpacity(.4),
),
),
),
)
\],
),
);
}
Widget searchbarWidget() {
final \_formKey = GlobalKey\<FormState\>();
return Container(
color: Colors.white,
child: Padding(
padding: cmargin(left: 25, right: 25, bottom: 20, top: 22),
child: Container(
height: HelperMethods().getMyDynamicHeight(36),
decoration: BoxDecoration(
color: Color(0xff767680).withOpacity(.12),
borderRadius: BorderRadius.circular(10)),
child: Row(
children: \[
Padding(
padding: cmargin(left: 8, right: 7.37),
child: Container(
height: HelperMethods().getMyDynamicHeight(15.78),
width: HelperMethods().getMyDynamicWidth(15.63),
child: Icon(
MyAwesomeIcons.loupe,
color: Color(0xff8E8E93),
size: HelperMethods().getMyDynamicWidth(15.63),
),
),
),
Expanded(
child: Form(
key: \_formKey,
child: TextFormField(
onSaved: (String \_value) {
if (!\_formKey.currentState.validate() ||
\_value.isEmpty) {
return;
}
print(\_value);
},
style: MyCustomTextStyles().body.copyWith(
color: SizeConfig.primaryTextColour, height: 1),
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Search',
hintStyle: MyCustomTextStyles().body.copyWith(
color: Color(0xff3C3C43).withOpacity(.6),
height: 1.1,
),
),
),
),
),
Padding(
padding: cmargin(right: 9.63),
child: Container(
height: HelperMethods().getMyDynamicHeight(16.37),
width: HelperMethods().getMyDynamicWidth(11),
child: Image.asset(
micIconString,
color: Color(0xff8E8E93),
fit: BoxFit.contain,
),
),
),
\],
),
),
));
}
Widget closeButton() {
return Container(
color: Colors.transparent,
height: HelperMethods().getMyDynamicWidth(55),
width: SizeConfig.screenWidth,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: \[
Padding(
padding: cmargin(right: 30, bottom: 25),
child: InkWell(
borderRadius: BorderRadius.circular(50),
onTap: () {
Navigator.pop(context);
},
child: Container(
decoration: BoxDecoration(
color: Colors.black.withOpacity(.2),
shape: BoxShape.circle,
),
height: HelperMethods().getMyDynamicWidth(30),
width: HelperMethods().getMyDynamicWidth(30),
child: Icon(
MyAwesomeIcons.close,
key: Key("close_button"),
size: HelperMethods().getMyDynamicWidth(30),
)),
),
)
\],
),
);
}
Widget sortDetailsContainer() {
return Expanded(
child: ModalProgressHUD(
inAsyncCall: false,
color: Colors.transparent,
child:
Container(
width: SizeConfig.screenWidth,
color: Colors.white,
child: Padding(
padding: cmargin(),
child: ListView(
padding: cmargin(),
children: List.generate(
avaiableCheckinItems.length + 1,
(index) => index == avaiableCheckinItems.length
? Container(
height: 50,
)
: InkWell(
key: Key(avaiableCheckinItems[index].displayName),
onTap: () {
//delayTime = DateTime.now();
if (avaiableCheckinItems[index].require &&
avaiableCheckinItems[index].selected) {
return;
}
avaiableCheckinItems[index].selected =
!avaiableCheckinItems[index].selected;
addToResponseBody(avaiableCheckinItems[index]);
setState(() {});
},
child: Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: SizeConfig.primaryTextColour
.withOpacity(.4),
width: HelperMethods()
.getMyDynamicFontSize(.35)))),
child: Padding(
padding: cmargin(
left: 30, top: 20, bottom: 20, right: 30),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
width:
HelperMethods().getMyDynamicWidth(244),
child: Row(
crossAxisAlignment:
CrossAxisAlignment.center,
children: [
Flexible(
child: Text(
avaiableCheckinItems[index]
.displayName,
style: MyCustomTextStyles()
.formText
.copyWith(
color: SizeConfig
.primaryTextColour,
height: 1),
),
),
avaiableCheckinItems[index].require
? Text(
' (required)',
style: MyCustomTextStyles()
.labelSmall
.copyWith(
color: SizeConfig
.primaryTextColour),
)
: Container()
],
),
),
Opacity(
opacity: avaiableCheckinItems[index]
.require &&
avaiableCheckinItems[index].selected
? .2
: 1,
child: CustomRadioButton(
onTap: (value) {
if (avaiableCheckinItems[index]
.require &&
avaiableCheckinItems[index]
.selected) {
return;
}
avaiableCheckinItems[index].selected =
!avaiableCheckinItems[index]
.selected;
addToResponseBody(
avaiableCheckinItems[index]);
setState(() {});
},
selected:
avaiableCheckinItems[index].selected,
),
)
],
),
),
),
)),
),
),
),
),
);
}
addToResponseBody(AvaiableCheckinItemModel checkInItem) {
if (responseBody\['show_checkins'\].containsKey(checkInItem.modelName)) {
responseBody\['show_checkins'\]\[checkInItem.modelName\]
\[checkInItem.dbVariable\] = checkInItem.selected;
} else {
responseBody\['show_checkins'\]\[checkInItem.modelName\] = {
checkInItem.dbVariable: checkInItem.selected
};
}
print(responseBody);
return;
}
updateAvaiableCheckInsResponse() {
Conn().connectivityResult().then((conn) async {
if (conn) {
final store = StoreProvider.of\<AppState\>(SizeConfig.rootPagecOntext);
String body = json.encode(responseBody);
responseBody = {'show_checkins': {}};
String token = await storage.read(key: "wildUserToken");
DashboardCheckInsModel oldCheckins =
store.state.dashboardDataModel.checkins;
store.state.dashboardDataModel.checkins = DashboardCheckInsModel();
store.dispatch(SetDashboardObject(store.state.dashboardDataModel));
if (widget.showLoading) {
await \_createCheckins(oldCheckins);
}
final response =
await http.post(Uri.encodeFull(widget.updateCheckinsUrl),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
"Authorization": "Token $token"
},
body: body);
if (response.statusCode == 200) {
store.state.dashboardDataModel.checkins = oldCheckins;
store.dispatch(updateDashboardCheckinCall(forceRefresh: true));
} else if (response.statusCode == 400 || response.statusCode == 500) {
var res = json.decode(response.body);
store.dispatch(SetDashboardObject(store.state.dashboardDataModel));
String msg = res\['details'\];
CustomAlert().showCustomAlert(
context, "Oops! Something went wrong. ", msg, AlertType.info);
} else {
store.dispatch(SetDashboardObject(store.state.dashboardDataModel));
// throw Exception("failed to load calendar");
}
} else {
ShowMyToastHelper().showCheckConnectionToast(context, 2);
}
});
}
Future \_createCheckins(DashboardCheckInsModel dashboardCheckInsModel) async {
await Conn().connectivityResult().then((bool conn) async {
if (conn) {
String body = json.encode(widget.checkInRequestBody);
String token = await storage.read(key: "wildUserToken");
final response = await http.post(
Uri.encodeFull(dashboardCheckInsModel.endpoints.submitCheckin.url),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
"Authorization": "Token $token"
},
body: body);
if (response.statusCode == 200) {
store.dispatch(checkInsUpdateGetDataCall(silenty: true));
}
} else {
ShowMyToastHelper().showCheckConnectionToast(context, 2);
}
});
}
}
the problem is the script runs and performs its actions but the test fails.
any guidance would be appreciated.if there is anymore information needed for clarification i'll be happy to provide it.

Why Flutter SfDataGrid sorting just renders sorted rows and no changes in datasource?

Im trying to use build-in sorting in my SfDataGrid. It works fine and flutter rerenders and show me sorted table, but when im trying to get cell value in table its bring me past(not sorted) value of cell.
So I want to not only render the sorted list but also sort the data source as well.
return FutureBuilder(
future: _portfolioDataSource.loadAndBuildPortfolioData(),
builder: (ctx, snapshot) {
asyncSnapshotErrorHandler(snapshot);
if (snapshot.connectionState == ConnectionState.done) {
return SfDataGridTheme(
data: SfDataGridThemeData(
headerColor: Color.fromRGBO(243, 243, 250, 1)),
child: SfDataGrid(
onSelectionChanged: _portfolioDataSource.isEntitiesEmpty
? null
: _onSelectionChanged,
gridLinesVisibility: GridLinesVisibility.horizontal,
headerGridLinesVisibility: GridLinesVisibility.horizontal,
highlightRowOnHover: true,
source: _portfolioDataSource,
frozenColumnsCount: _portfolioDataSource.isEntitiesEmpty
? 0
: widget.frozenColumnsCount,
columnWidthMode: ColumnWidthMode.none,
allowPullToRefresh: true,
allowSorting: false,
allowMultiColumnSorting: false,
showSortNumbers: true,
loadMoreViewBuilder:
(BuildContext context, LoadMoreRows loadMoreRows) {
bool showIndicator = false;
return StatefulBuilder(builder:
(BuildContext context, StateSetter setState) {
if (showIndicator) {
return Container(
height: 60.0,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
border: BorderDirectional(
top: BorderSide(
width: 1.0,
color:
Color.fromRGBO(0, 0, 0, 0.26)))),
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(
Color.fromRGBO(18, 183, 106, 1),
)));
} else {
return Container(
height: 60.0,
width: double.infinity,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.white,
border: BorderDirectional(
top: BorderSide(
width: 1.0,
color:
Color.fromRGBO(0, 0, 0, 0.26)))),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
margin:
EdgeInsets.symmetric(horizontal: 20),
height: 36.0,
width: 142.0,
child: TextButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(
Color.fromRGBO(18, 183, 106, 1),
)),
child: Text('LOAD MORE',
style: TextStyle(
color: Colors.white)),
onPressed: () async {
_onSelectionChanged([], []);
if (context is StatefulElement &&
context.state.mounted) {
setState(() {
print(
widget.selectedInstanceIds);
showIndicator = true;
});
}
await loadMoreRows();
if (context is StatefulElement &&
context.state.mounted) {
setState(() {
showIndicator = false;
});
}
})),
Container(
margin:
EdgeInsets.symmetric(horizontal: 20),
height: 36.0,
width: 142.0,
child: TextButton(
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(
Color.fromRGBO(18, 183, 106, 1),
)),
child: Text('LOAD ALL',
style: TextStyle(
color: Colors.white)),
onPressed: () async {
if (context is StatefulElement &&
context.state.mounted) {
setState(() {
showIndicator = true;
});
}
await _portfolioDataSource
.loadAllRows();
if (context is StatefulElement &&
context.state.mounted) {
setState(() {
showIndicator = false;
});
}
})),
],
));
}
});
},
And DataSource
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_datagrid/datagrid.dart';
import 'package:zwe_spmis_mobile/models/controls/portfolio-control/portfolio_configs.dart';
import 'package:zwe_spmis_mobile/services/portfolio_service.dart';
import '../../../services/api/entity_search_service.dart';
import '../../../services/provider/service_provider.dart';
import '../../../utils/entity_helpers/filter/filter_builder.dart';
import '../../../zwe_icons_icons.dart';
import '../../entity.dart';
import '../../portfolio_items_state.dart';
class PortfolioDataSource extends DataGridSource {
final List<dynamic> _entities = [];
List<int> downloadedItemIds = [];
List<DataGridRow> _dataGridRows = [];
PortfolioService _portfolioService = new PortfolioService();
PortfolioItemsState _portfolioItemsState;
final FilterBuilder _filter;
final String _categorySystemName;
final Function buildDataGridRows;
final highlitedFieldSystemName;
String? bulkAction;
int pageNumber = 0;
int countPerPage = 20;
String sortFields = "DateUpdated";
bool isEntitiesEmpty = false;
EntitySearchService _offlineEntitySearchService =
ServiceProvider.getOfflineContext().getEntitySearchService();
PortfolioDataSource(
this._portfolioItemsState,
this._filter,
this._categorySystemName,
this.buildDataGridRows,
this.highlitedFieldSystemName,
this.countPerPage,
this.pageNumber,
{this.bulkAction: null});
Future<void> handleLoadMoreRows() async {
this.pageNumber++;
await loadMoreAndBuildPortfolioData();
}
Future<void> loadAllRows() async {
this.pageNumber = 0;
this.countPerPage = 500;
await loadAndBuildPortfolioData();
this.pageNumber = 25;
this.countPerPage = 20;
}
#override
List<DataGridRow> get rows => _dataGridRows;
#override
DataGridRowAdapter? buildRow(DataGridRow row) {
TextStyle? getTextStyle(DataGridCell<dynamic> dataGridCell) {
return TextStyle(
color: dataGridCell.columnName == ''
? Color.fromRGBO(19, 180, 105, 1)
: null);
}
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((dataGridCell) {
return Container(
alignment: (dataGridCell.columnName == 'id')
? Alignment.centerRight
: Alignment.centerLeft,
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: dataGridCell.columnName == 'actions'
? RichText(
text: TextSpan(
children: [
WidgetSpan(
child: (dataGridCell.value.toString() == 'Download')
? Icon(
ZweIcons.download,
size: 20,
color: Color.fromRGBO(19, 180, 105, 1),
)
: (dataGridCell.value.toString() == 'Submit')
? RichText(
text: TextSpan(
style: TextStyle(
color:
Color.fromRGBO(19, 180, 105, 1),
fontWeight: FontWeight.w900),
children: [
WidgetSpan(
child: Icon(
Icons.upload,
size: 20,
color: Color.fromRGBO(
19, 180, 105, 1),
),
),
],
),
)
: Text('')),
TextSpan(
style: dataGridCell.value.toString() == 'Downloaded' ||
dataGridCell.value.toString() == 'Delete'
? TextStyle(
color: Color.fromRGBO(19, 180, 105, 1),
fontWeight: FontWeight.w900)
: TextStyle(color: Color.fromRGBO(19, 180, 105, 1)),
text: dataGridCell.value.toString(),
),
],
),
)
: dataGridCell.columnName == 'sync'
? RichText(
text: TextSpan(
children: [
WidgetSpan(
child: Icon(
Icons.upload,
size: 20,
color: Color.fromRGBO(19, 180, 105, 1),
),
),
TextSpan(
style: TextStyle(
color: Color.fromRGBO(19, 180, 105, 1)),
text: "Submit",
),
],
),
)
: Text(
dataGridCell.value.toString(),
overflow: TextOverflow.ellipsis,
style: TextStyle(
color: dataGridCell.columnName ==
this.highlitedFieldSystemName
? Color.fromRGBO(44, 121, 231, 1)
: dataGridCell.columnName == 'actions'
? Color.fromRGBO(19, 180, 105, 1)
: null),
));
}).toList());
}
addItem(Entity ent, String? bulkAction) {
_entities.add(ent);
_dataGridRows = buildDataGridRows(_entities, bulkAction);
notifyListeners();
}
Future<List<int>> loadDownloadedItemIds() {
return _offlineEntitySearchService.loadAllEntityIds(_categorySystemName);
}
removeItem(int entityInstanceId) {
this.downloadedItemIds.remove(entityInstanceId);
this
._entities
.removeWhere((element) => element['instanceId'] == entityInstanceId);
_dataGridRows.removeWhere((element) =>
element.getCells()[element.getCells().length - 1].value ==
entityInstanceId);
}
Future<List<Map<String, dynamic>>> loadCreatedItems() {
return _offlineEntitySearchService.loadEntitiesByInstanceIds(
this._categorySystemName,
downloadedItemIds.where((element) => element < 0).toList());
}
Future<void> loadAndBuildPortfolioData() async {
_entities.length = 0;
_entities.addAll(await loadCreatedItems());
this.downloadedItemIds = await loadDownloadedItemIds();
if (this.bulkAction == 'Download') {
_portfolioItemsState = PortfolioItemsState.NOT_DOWNLOADED;
}
await _portfolioService
.loadEntitiesByFilter(
_categorySystemName,
_portfolioItemsState,
sortFields,
countPerPage,
pageNumber,
_filter,
serializationFields[_categorySystemName])
.then((List<dynamic> value) {
_entities.addAll(value);
_dataGridRows =
buildDataGridRows(_entities, downloadedItemIds, bulkAction);
isEntitiesEmpty = (_entities.length == 0);
notifyListeners();
});
}
}
You can get the sorted row collection from the DataGridSource.effectiveRows property. It holds the sorted collection if the sorting is applied in DataGrid.
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key}) : super(key: key);
#override
MyHomePageState createState() => MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
List<Employee> _employees = <Employee>[];
late EmployeeDataSource _employeeDataSource;
#override
void initState() {
super.initState();
_employees = _getEmployeeData();
_employeeDataSource = EmployeeDataSource(employeeData: _employees);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Flutter DataGrid')),
body: Column(
children: [
Container(
margin: const EdgeInsets.all(30),
child: ElevatedButton(
onPressed: (() {
// You can get a sorted collection from effectiveRows property.
for (var details in _employeeDataSource.effectiveRows) {
print(details.getCells()[0].value);
}
}),
child: const Text('Get Sorted Collection')),
),
Expanded(
child: SfDataGrid(
source: _employeeDataSource,
allowSorting: true,
columnWidthMode: ColumnWidthMode.fill,
columns: <GridColumn>[
GridColumn(
columnName: 'ID',
label: Container(
padding: const EdgeInsets.all(8.0),
alignment: Alignment.center,
child: const Text('ID'))),
GridColumn(
columnName: 'Name',
label: Container(
padding: const EdgeInsets.all(8.0),
alignment: Alignment.center,
child: const Text('Name'))),
GridColumn(
columnName: 'Designation',
label: Container(
padding: const EdgeInsets.all(8.0),
alignment: Alignment.center,
child: const Text('Designation'))),
GridColumn(
columnName: 'Salary',
label: Container(
padding: const EdgeInsets.all(8.0),
alignment: Alignment.center,
child: const Text('Salary'))),
],
),
),
],
),
);
}
}
class EmployeeDataSource extends DataGridSource {
EmployeeDataSource({required List<Employee> employeeData}) {
_employeeData = employeeData
.map<DataGridRow>((Employee e) => DataGridRow(cells: <DataGridCell>[
DataGridCell<int>(columnName: 'ID', value: e.id),
DataGridCell<String>(columnName: 'Name', value: e.name),
DataGridCell<String>(
columnName: 'Designation', value: e.designation),
DataGridCell<int>(columnName: 'Salary', value: e.salary),
]))
.toList();
}
List<DataGridRow> _employeeData = <DataGridRow>[];
#override
List<DataGridRow> get rows => _employeeData;
#override
DataGridRowAdapter buildRow(DataGridRow row) {
return DataGridRowAdapter(
cells: row.getCells().map<Widget>((DataGridCell cell) {
return Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(8.0),
child: Text(cell.value.toString()),
);
}).toList());
}
}
class Employee {
Employee(this.id, this.name, this.designation, this.salary);
final int id;
final String name;
final String designation;
final int salary;
}
List<Employee> _getEmployeeData() {
return <Employee>[
Employee(10001, 'James', 'Manager', 90000),
Employee(10002, 'Kathryn', 'Project Lead', 75000),
Employee(10003, 'Lara', 'Developer', 45000),
Employee(10004, 'Michael', 'Designer', 37000),
Employee(10005, 'Martin', 'Developer', 43000),
];
}

How to display the saved state of a button when the page opens?

I have three buttons. The maximum that I can select (activate) is only one button. When switching buttons, I have activated should be true, and not activated - false. I write these values ​​to SharedPreferences for each button, store true or false. When I open the pages all the buttons are gray out (they are not selected). I need to save the button state that it was selected and display it when the page is opened. For example, I just need if the variable isVoltageAC = true, then the AC button will immediately turn purple when the page is opened. How to do it?
enum VoltageMode {
ac,
dc,
all,
}
class FilterDialog extends StatefulWidget {
const FilterDialog({
Key? key,
}) : super(key: key);
#override
State<FilterDialog> createState() => _FilterDialogState();
}
class _FilterDialogState extends State<FilterDialog> {
VoltageMode? selectedMode;
#override
Widget build(BuildContext context) {
return BlocBuilder<MapPreferencesCubit, MapPreferencesState>(
builder: (context, statePreferences) {
final MapPreferencesCubit mapPreferencesCubit =
BlocProvider.of<MapPreferencesCubit>(context);
if (statePreferences is MapPreferencesInitial) {
mapPreferencesCubit.getPreferences();
}
if (statePreferences is MapPreferencesLoaded) {
return BlocBuilder<MapfilterCubit, MapFilterState>(
builder: (context, stateFilter) {
final MapfilterCubit mapFilterCubit =
BlocProvider.of<MapfilterCubit>(context);
if (stateFilter is MapFilterInitial) {
mapFilterCubit.getFilter();
}
if (stateFilter is MapFilterLoaded) {
bool isVoltageAC = stateFilter.mapFilter.voltagePowerAC;
bool isVoltageDC = stateFilter.mapFilter.voltagePowerDC;
bool isVoltageAll = stateFilter.mapFilter.voltagePowerAll;
return SingleChildScrollView(
child: Dialog(
insetPadding: const EdgeInsets.only(
top: 121, left: 24, right: 24, bottom: 60),
child: Container(
decoration: const BoxDecoration(
color: constants.Colors.greyDark,
borderRadius: BorderRadius.all(Radius.circular(24)),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(0, 26, 0, 24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [,
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 21),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GestureDetector(
onTap: () => setState(() {
selectedMode = VoltageMode.ac;
}),
child: _buttonVoltage(
'AC', selectedMode == VoltageMode.ac),
),
const SizedBox(width: 16),
GestureDetector(
onTap: () => setState(() {
selectedMode = VoltageMode.dc
}),
child: _buttonVoltage(
'DC', selectedMode == VoltageMode.dc),
),
const SizedBox(width: 16),
GestureDetector(
onTap: () => setState(() {
selectedMode = VoltageMode.all;
}),
child: _buttonVoltage(
'All', selectedMode == VoltageMode.all),
),
],
),
),
Padding(
padding:
const EdgeInsets.symmetric(horizontal: 21),
child: DefaultButtonGlow(
text: 'Done',
onPressed: () {
Navigator.pop(context);;
mapFilterCubit
.setFilter(
MapFilter(
voltagePowerAC:
selectedMode == VoltageMode.ac,
voltagePowerDC:
selectedMode == VoltageMode.dc,
voltagePowerAll:
selectedMode == VoltageMode.all,
),
)
},
),
Widget _buttonVoltage(String nameButton, bool isActive) => Container(
padding: const EdgeInsets.symmetric(vertical: 11),
height: 40,
width: 87,
decoration: BoxDecoration(
color: isActive
? constants.Colors.purpleMain
: constants.Colors.white.withOpacity(0.15),
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: isActive ? Colors.transparent : constants.Colors.greyDark,
),
boxShadow: [
BoxShadow(
color: isActive
? constants.Colors.purpleMain.withOpacity(0.34)
: Colors.transparent,
blurRadius: 10,
spreadRadius: 2,
offset: const Offset(0.0, 1.0)),
],
),
alignment: Alignment.center,
child:
Text(nameButton, style: constants.Styles.smallBoldTextStyleWhite),
);
cubit
Future setFilter(MapFilter mapFilter) async {
await _repository.setFilter(mapFilter: mapFilter);
final MapFilter? filter = await _repository.getFilter();
emit(MapFilterLoaded(filter!));
return filter;}
sharedpreferences
Future setFilter({required MapFilter mapFilter}) async {
final SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString(_filterName, jsonEncode(mapFilter.toJson()));
}
you can read this values from SharedPreferences in initState of page. In this way your default value is ready when page loaded.
then make everything after SingleChildScrollView in separate widget like this:
Widget _buildBody(){
return SingleChildScrollView(
child: Dialog(
...
),
);
}
and pass this widget in your bloc builder after all if statement by default.
then do this:
void initState() {
super.initState();
final SharedPreferences prefs = await SharedPreferences.getInstance();
var result = prefs.readData(_filterName);
if (result != null) {
MapFilter mapFilter = jsonDecode(mapFilter.fromJson(result));
if (mapFilter.voltagePowerAC){
selectedMode = VoltageMode.ac;
}else if (mapFilter.voltagePowerDC){
selectedMode = VoltageMode.dc;
} else {
selectedMode = VoltageMode.all;
}
}
}

Having issue with my favorite button functionality in flutter

I am having an issue with my favorite button. I have connected it with real-time firebase and each time I press the favorite icon it changes the state in firebase either true or false. when I press the heart button it always shows me different output sometimes it becomes red or black without affecting the other and sometimes it changes the other ones too (red or black). I have tried a lot to solve this but I am unable to get a solution for it.
class Home_page extends StatefulWidget {
#override
State<Home_page> createState() => _Home_pageState();
}
class _Home_pageState extends State<Home_page> {
//late StreamSubscription _dailySpecialStream;
var clr = Colors.grey;
//var item;
final List<String> _listItem = [
'assets/audi3.png',
'assets/audi.png',
'assets/audi2.png',
'assets/audi.png',
'assets/audi2.png',
'assets/audi3.png',
];
var name;
var auth1 = FirebaseAuth.instance.currentUser;
Data? c;
late final Value;
List<Data> dataList = [];
List<dynamic> d = [];
List<dynamic> favList = [];
#override
void initState() {
print("object");
super.initState();
print(auth1);
_activateListener();
}
void _activateListener() {
final _database = FirebaseDatabase.instance.ref();
_database.child('user').get().then((snapshot) {
dataList.clear();
favList.clear();
print("hello");
Value = snapshot.value as Map;
final datas = snapshot.children.forEach((element) {
d.add(element.key);
});
for (var k in d) {
//print("");
print(Value[k]['imgUrl']);
print((Value[k]['carName']).runtimeType);
dataList.add(Data(
Value[k]['carName'],
Value[k]['price'],
Value[k]["imgUrl"],
k,
));
if (auth1 != null) {
print(k);
print("auth1");
print(auth1);
DatabaseReference reference = FirebaseDatabase.instance
.ref()
.child("user")
.child(k)
.child("fav")
.child(auth1!.uid)
.child("state");
reference.get().then((s) {
print(s.value);
print("upp is vla");
if (s.value != null) {
if (s.value == true) {
// print(s.value);
// print("true");
favList.add(true);
print(favList);
} else {
//print(s.value);
print("false1");
favList.add(false);
//print(favList);
}
} else {
print("inelse");
favList.add(false);
print(favList);
}
});
}
}
Timer(Duration(seconds: 1), () {
setState(() {
inspect(favList);
});
});
});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: Container(
color: Colors.white,
child: Stack(
children: [
Image.asset(
"assets/top.png",
fit: BoxFit.cover,
),
Column(
children: [
SizedBox(
height: 30,
),
search(context),
SizedBox(
height: 80,
),
Expanded(
child: GridView.count(
crossAxisCount: 2,
crossAxisSpacing: 10,
mainAxisSpacing: 40,
children: List.generate(
dataList.length, (index) => GridDesign(index)).toList(),
)),
],
)
],
),
),
),
);
}
SizedBox GridDesign(int index) {
return SizedBox(
child: Column(
children: [
Stack(
clipBehavior: Clip.none,
children: [
Container(
height: 15.h,
width: 45.w,
margin: EdgeInsets.only(left: 12, top: 12, right: 16),
decoration: BoxDecoration(
// border: Border.all(color: Colors.grey,style: BorderStyle.solid,width: 2),
borderRadius: BorderRadius.circular(5),
image: DecorationImage(
image: NetworkImage(dataList[index].url.toString()),
fit: BoxFit.cover)),
),
Positioned(
bottom: -3,
right: 5,
child: Container(
height: 32,
width: 32,
child: Neumorphic(
padding: EdgeInsets.zero,
style: NeumorphicStyle(
//shape: NeumorphicShape.concave,
boxShape: NeumorphicBoxShape.roundRect(
BorderRadius.circular(50)),
color: Colors.white),
child: favList[index]
? IconButton(
padding: EdgeInsets.zero,
onPressed: () {
if (auth1 != null) {
print(auth1);
print("it's not null");
DatabaseReference favRef = FirebaseDatabase
.instance
.ref()
.child("user")
.child(
dataList[index].uploadId.toString())
.child("fav")
.child(auth1!.uid)
.child("state");
favRef.set(false);
setState(() {
favFun();
});
}
print("object");
},
icon: Icon(
Icons.favorite,
color: Colors.red,
),
)
: IconButton(
padding: EdgeInsets.zero,
onPressed: () {
if (auth1 != null) {
print("it's not null1");
print(auth1);
DatabaseReference favRef = FirebaseDatabase
.instance
.ref()
.child("user")
.child(
dataList[index].uploadId.toString())
.child("fav")
.child(auth1!.uid)
.child("state");
favRef.set(true);
setState(() {
favFun();
});
}
print("object");
},
icon: Icon(
Icons.favorite,
))),
),
),
],
),
SizedBox(
height: 4,
),
Expanded(child: Text(dataList[index].CarName.toString())),
SizedBox(height: 2),
Expanded(
child: Text("R" + dataList[index].price.toString()),
),
SizedBox(height: 3),
Expanded(
child: ElevatedButton(
onPressed: () =>
Get.to(DetailPage(dataList[index].Url, dataList[index].Price)),
child: Text("Details"),
style: ElevatedButton.styleFrom(primary: myColor),
))
],
),
);
}
void favFun() {
final _database = FirebaseDatabase.instance.ref();
_database.child('user').get().then((snapshot) {
favList.clear();
for (var k in d) {
//print("");
if (auth1 != null) {
print(k);
print("auth1");
print(auth1);
DatabaseReference reference = FirebaseDatabase.instance
.ref()
.child("user")
.child(k)
.child("fav")
.child(auth1!.uid)
.child("state");
reference.once().then((DatabaseEvent s) {
print(s.snapshot.value);
print("upp is vla");
if (s.snapshot.value != null) {
if (s.snapshot.value == true) {
// print(s.value);
// print("true");
favList.add(true);
print(favList);
} else {
//print(s.value);
print("false1");
favList.add(false);
//print(favList);
}
} else {
print("inelse");
favList.add(false);
print(favList);
}
});
}
}
Timer(Duration(seconds: 1), () {
setState(() {
//inspect(favList);
});
});
});
}
}
Have a look at the picture to get a better view

Flutter Stateful Widget used across Multiple Screens getting Rebuilt

ive created the below Multiselect Chip Widget its using Provider and Listening for changes to the list
the widget creates a List of Choice Chips that allows multiple choice chips to be chosen
class MultiSelectChip extends StatefulWidget {
final Function(List<String>) onSelectionChanged;
MultiSelectChip({this.onSelectionChanged});
#override
_MultiSelectChipState createState() => _MultiSelectChipState();
}
class _MultiSelectChipState extends State<MultiSelectChip> {
List<String> selected = List();
List<Clinic> clinicList = List();
#override
void didChangeDependencies() {
final list = Provider.of<ClinicProvider>(context).clinics;
final clinic = Clinic(
id: null,
name: "All Clinics",
city: null,
suburb: null,
postcode: null,
prate: null,
udarate: null,
goal: null,
uid: null);
clinicList.add(clinic);
selected.add(clinicList[0].name);
list.forEach((clinic) => clinicList.add(clinic));
super.didChangeDependencies();
}
_buildList() {
List<Widget> choices = List();
clinicList.forEach((item) {
choices.add(Padding(
padding: const EdgeInsets.only(left: 5.0, right: 5.0),
child: ChoiceChip(
key: Key("${item.name}"),
shape: selected.contains(item.name)
? RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(0),
),
)
: RoundedRectangleBorder(
side: BorderSide(
color: Color.fromRGBO(46, 54, 143, 1), width: 1.0),
borderRadius: BorderRadius.circular(0.0),
),
label: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(item.name),
),
onSelected: (value) {
setState(() {
selected.contains(item.name)
? selected.remove(item.name)
: selected.add(item.name);
widget.onSelectionChanged(selected);
});
},
selected: selected.contains(item.name),
selectedColor: Color.fromRGBO(46, 54, 143, 1),
labelStyle:
selected.contains(item.name) ? kChipActive : kChipInActive,
backgroundColor: Colors.transparent,
),
));
});
return choices;
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 8.0, top: 5.0, bottom: 5.0),
child: SizedBox(
height: 50,
width: double.infinity,
child: ListView(
scrollDirection: Axis.horizontal,
children: _buildList(),
),
),
);
}
}
when i click from this Log screen and goto the NewLog screen and Pop Back to the Log Screen
class LogScreen extends StatefulWidget {
static const String id = 'logscreen';
#override
_LogScreenState createState() => _LogScreenState();
}
class _LogScreenState extends State<LogScreen> {
MonthSelector selectedMonth;
List<String> selectedItems = List();
static DateTime now = DateTime.now();
static DateTime end = DateTime(now.year, now.month + 1, 0);
static DateTime start = DateTime(now.year, now.month, 1);
MonthSelector currentMonth = MonthSelector(
monthName: DateFormat("MMMM").format(now),
monthStart: start,
monthEnd: end);
void refreshData(MonthSelector selector) async {
await Provider.of<LogProvider>(context, listen: false)
.getLogs(selector.monthStart, selector.monthEnd);
await Provider.of<LogProvider>(context, listen: false)
.loadTreatments(selector.monthStart, selector.monthEnd);
}
#override
Widget build(BuildContext context) {
final List<LogSummary> list = Provider.of<LogProvider>(context).summary;
final List<FlSpot> chartData = Provider.of<LogProvider>(context).spots;
return Container(
color: Color.fromRGBO(246, 246, 246, 1),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
flex: 1,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
height: 15,
),
RawMaterialButton(
onPressed: () {
Navigator.pushNamed(context, NewLogScreen.id);
},
constraints: BoxConstraints.tight(Size(60, 60)),
child: Icon(
Icons.add,
color: Color.fromRGBO(255, 255, 255, 1),
size: 30,
),
shape: CircleBorder(),
fillColor: Color.fromRGBO(46, 54, 143, 1),
padding: EdgeInsets.all(15.0),
elevation: 1,
),
SizedBox(
height: 10,
),
Text(
'Add log',
style: kAddLogLabel,
)
],
),
),
]),
list.isEmpty || chartData.isEmpty
? Expanded(
child: Center(
child: Text("No Log Data.."),
),
)
: Expanded(
child: Column(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
height: 150,
alignment: Alignment.center,
child: LineChartWidget(
list: chartData,
isDollar: true,
),
),
SizedBox(
height: 10,
),
MultiSelectChip(
onSelectionChanged: (selectedList) async {
setState(() {
selectedItems = selectedList;
});
await Provider.of<LogProvider>(context, listen: false)
.filterLogList(selectedItems);
},
),
MonthSelect(Color.fromRGBO(246, 246, 246, 1),
onMonthSelectionChanged: (selected) {
setState(() {
selectedMonth = selected;
});
selectedMonth == null
? refreshData(currentMonth)
: refreshData(selectedMonth);
}),
Padding(
padding:
const EdgeInsets.only(top: 10, left: 0, right: 0),
child: Container(
width: double.infinity,
height: 1.0,
color: kDividerColor,
),
),
what i am seeing is the Multiselect Chip has the Same List of Items redrawn/added to the list view 3 times, each time i go into the NewLog screen the list keeps growing
im currently using the same Widget across 4 diffrent screens, but for some reason when i navigate to one of the other screen the list resets and displays the orignal items and the duplicate items dissapear
what can i do to prevent this from redrawing, all the time when navigating off the screen
thanks
Have you tried specifying listen: false in Provider.of() used in didChangeDependencies()? It may solve the issue.
However, there can still be a risk. I doubt initialising something there is safe because didChangeDependencies() is called when/whenever a dependency of the State object changes as written in its document. It'd be safer to do it in initState(), or have it done outside only once and its result passed in to MultiSelectChip.