This is my output
all these functions are works excellent. But I tried to add sharedPrefence to these dropdowns, select birthday and to the checkbox. But both dropdowns work perfectly, When I select something in the dropdown and click the next button and close the app and reopen again then shows the words that are selected at the last. But after that, I tried to add sharedPrefence to datePicker and thin "Are you agree " check box but then shows some errors. I have no idea how to solve that. EX:- In this, I used a date picker, Agree checkbox and in there shows "Birthday" word as an initial date and check box is unselecting, when the click selects the button then shows the dates and pick date and can select check box then value is true, That works perfectly. But I wanna add shared Preferences to this When added that, after the selected word and close the app and reopened again then should show the date and check box value true that is selected at the last.
my full code.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class FamilyDetailsScreen extends StatefulWidget {
@override
State<FamilyDetailsScreen> createState() => _FamilyDetailsScreenState();
}
class _FamilyDetailsScreenState extends State<FamilyDetailsScreen> {
// 1st dropdown button
@override
void initState() {
super.initState();
dropdownValueMembers = items.first;
dropdownValueNumber = number.first;
dropdownValueBirthday = birthday.first;
dropdownValueBirthday = Agree.first;
checkValueMembers();
checkValueNumber();
checkValueBirthday();
checkValueAgree();
}
String? dropdownValueMembers;
// List of items in our dropdown menu
List<String> items = [
'howmany',
'one',
'two',
'three ',
'four',
'5 or more'
];
checkValueMembers() {
_getData();
}
_saveData(String dropdownValueMembersShared) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString("data", dropdownValueMembersShared);
}
_getData() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
dropdownValueMembers = sharedPreferences.getString("data") ?? items.first;
setState(() {});
}
// 2nd dropdown button
// data which child
String? dropdownValueNumber;
// // List of items in our dropdown menu
List<String> number = ['which', '1 st', '2 nd', '3 rd ', '4 th ', '5 th'];
//IF "dropdownValueMembers" is empty pass "which" word as a initial value if al ready selected then pass the shared preference value
checkValueNumber() {
_getDataNumber();
}
_saveDataNumbers(String dropdownValueNumberShared) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString("data2", dropdownValueNumberShared);
}
_getDataNumber() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
dropdownValueNumber = sharedPreferences.getString("data2") ?? number.first;
setState(() {});
}
//date picker
DateTime? selectedDate;
DateTime now = new DateTime.now();
void showDatePicker() {
DateTime mindate = DateTime(now.year - 2, now.month, now.day - 29);
DateTime maxdate = DateTime(now.year - 1, now.month, now.day);
showCupertinoModalPopup(
context: context,
builder: (BuildContext builder) {
return Container(
height: MediaQuery.of(context).copyWith().size.height * 0.25,
color: Colors.white,
child: CupertinoDatePicker(
mode: CupertinoDatePickerMode.date,
initialDateTime: mindate,
onDateTimeChanged: (value) {
if (value != null && value != selectedDate) {
setState(() {
selectedDate = value;
});
}
},
maximumDate: maxdate,
minimumDate: mindate,
),
);
});
}
String? dropdownValueBirthday;
List<String> birthday = [
'Birthday',
];
//sharedPreferences birthday
checkValueBirthday() {
_getDataBirthday();
}
_saveDataBirthday(String dropdownValueBirthdayShared) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setString("dataBirthday", dropdownValueBirthdayShared);
}
_getDataBirthday() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
dropdownValueBirthday =
sharedPreferences.getString("dataBirthday") ?? birthday.first;
setState(() {});
}
//////////////////////////////////
// are you agree button
//boolean value (are you agree)
bool isChecked = false;
checkValueAgree() {
_getDataAgree();
}
_saveDataAgree(String dropdownValueAgreeShared) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
sharedPreferences.setBool("Agree", dropdownValueAgreeShared);
}
_getDataAgree() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
dropdownValueNumber = sharedPreferences.getBool("Agree") ?? isChecked.first;
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
body: SafeArea(
child: Column(
children: <Widget>[
const Text(
'family details',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontSize: 18.00,
fontWeight: FontWeight.w700,
),
),
const SizedBox(
height: 30,
),
Padding(
padding: const EdgeInsets.only(top: 10, left: 15),
child: Row(
children: <Widget>[
const Icon(
Icons.brightness_1,
color: Colors.black,
size: 10.0,
),
const Padding(
padding: EdgeInsets.only(left: 13),
child: Text(
"Number of children",
style:
TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
),
),
],
),
),
const SizedBox(
height: 25,
),
Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 2),
child: Container(
height: 25,
decoration: BoxDecoration(
boxShadow: const <BoxShadow>[
//apply shadow on Dropdown button
BoxShadow(
color: Color.fromRGBO(
0, 0, 0, 0.37), //shadow for button
blurRadius: 5) //blur radius of shadow
],
color: Colors.white,
borderRadius: BorderRadius.circular(15),
),
child: DropdownButton(
underline: Container(),
borderRadius: BorderRadius.circular(20),
// Initial Value
value: dropdownValueMembers,
// Down Arrow Icon
icon: const Icon(Icons.keyboard_arrow_down),
// Array list of items
items: items.map((String data) {
return DropdownMenuItem(
value: data,
child: SizedBox(
height: 15,
width: 120.0, // for example
child: Text(data,
style: const TextStyle(
fontSize: 13.0,
fontWeight: FontWeight.w700),
textAlign: TextAlign.center),
),
);
}).toList(),
// After selecting the desired option,it will
// change button value to selected value
onChanged: (String? newValue) {
setState(
() {
dropdownValueMembers = newValue!;
},
);
},
),
),
),
],
),
Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 20),
child: Text('Which child'),
),
Padding(
padding: const EdgeInsets.only(left: 100, right: 0, top: 20),
child: Container(
height: 30,
decoration: BoxDecoration(
boxShadow: const <BoxShadow>[
//apply shadow on Dropdown button
BoxShadow(
color: Color.fromRGBO(
0, 0, 0, 0.37), //shadow for button
blurRadius: 5) //blur radius of shadow
],
color: Colors.white,
borderRadius: BorderRadius.circular(15),
),
child: DropdownButton(
underline: Container(),
borderRadius: BorderRadius.circular(20),
// Initial Value
value: dropdownValueNumber,
// Down Arrow Icon
icon: const Icon(Icons.keyboard_arrow_down),
// Array list of items
items: number.map((String number) {
return DropdownMenuItem(
value: number,
child: SizedBox(
height: 17,
width: 120.0, // for example
child: Text(number,
style: const TextStyle(
fontSize: 13.0,
fontWeight: FontWeight.w700),
textAlign: TextAlign.center),
),
);
}).toList(),
// After selecting the desired option,it will
// change button value to selected value
onChanged: (String? newNumber) {
setState(
() {
dropdownValueNumber = newNumber!;
},
);
},
),
),
),
],
),
const SizedBox(
height: 60,
),
Padding(
padding: const EdgeInsets.only(left: 15),
child: Row(
children: <Widget>[
const Icon(
Icons.brightness_1,
color: Colors.black,
size: 10,
),
const Padding(
padding: EdgeInsets.only(left: 15.0),
child: Text("birthday",
style: TextStyle(
fontSize: 16.0,
)),
),
Padding(
padding: const EdgeInsets.only(left: 25.0),
child: SizedBox(
width: 110.0,
height: 25.0,
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
),
child: Center(
child: Text(
selectedDate == null
? (dropdownValueBirthday ?? birthday.first)
: '${selectedDate?.year}/${selectedDate?.month}/${selectedDate?.day} ',
style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.w500),
),
),
),
),
),
Padding(
padding: const EdgeInsets.only(left: 15.0),
child: SizedBox(
width: 88.0,
height: 25.0,
child: MaterialButton(
onPressed: showDatePicker,
shape: const StadiumBorder(),
color: Colors.blue,
child: const Text(
'select',
style: TextStyle(color: Colors.white, fontSize: 12),
),
),
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Row(
children: <Widget>[
const Icon(
Icons.brightness_1,
color: Colors.black,
size: 10,
),
const Padding(
padding: EdgeInsets.only(left: 15.0),
child: Text(
"Are you agree",
style:
TextStyle(fontSize: 16, fontWeight: FontWeight.w500),
),
),
const Padding(
padding: EdgeInsets.only(left: 30),
child: Text(
'yes',
style:
TextStyle(fontSize: 15, fontWeight: FontWeight.bold),
),
),
Checkbox(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
side: MaterialStateBorderSide.resolveWith(
(states) =>
BorderSide(width: 3.0, color: Colors.blueAccent),
),
value: isChecked,
onChanged: (bool? value) {
setState(() {
isChecked = value!;
});
},
),
],
),
),
Padding(
padding: const EdgeInsets.only(bottom: 0.0, top: 150),
child: SizedBox(
width: 160.0,
height: 35.0,
child: ElevatedButton(
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(18.0),
side: const BorderSide(
color: Colors.blueAccent,
),
),
),
),
onPressed: () {
//do null check 1st
_saveData(dropdownValueMembers!);
_saveDataNumbers(dropdownValueNumber!);
_saveDataBirthday(dropdownValueBirthday!);
_saveDataAgree(isChecked!);
},
child: const Text('next')),
),
),
],
),
),
);
}
}
How to solve and how to add sharedPreference to this datepicker and to checkbox
Lot's of ways to go about it. Simplist way in your case, get rid of all the setStates in all your methods except the last one. You're layering all those setStates and they're calling while other things are still awaiting.
I suggest awaiting each method before calling any setState. You can't await in the initState, but in the first method, call the each of the subsequent ones with awaits from there. So just call checkValueMembers(); (or create a new one getAllValues or whatever).
Within getAllValues, await all the other methods.
Then you can be sure that everything is done, and finally, call setState this way:
WidgetsBinding.instance.addPostFrameCallback((_) {
setState((){});
});
It ensures you don't call setState until the entire widget tree is done.
Entire thing could look like this: remember to get rid of all the other setStates
Future checkValueMembers() async {
await _getData();
await _getDataNumber();
await _getDataBirthday();
await _getDataAgree();
WidgetsBinding.instance.addPostFrameCallback((_) {
setState((){});
});
}