我的应用程序上有一个个人资料页面,其中包含包含个人信息的卡片。用户单击以打开AlertDialog,并且AlertDialog中有一个字段,用于更新Firestore中的信息。在这种情况下,用户从CupertinoDatePicker中选择生日。我的问题是,滚动日期时,后台的个人资料页面会不断重建。
从下面的代码中可以找到,我用一个StreamBuilder对其进行设置。我尝试将其设置为每张Card都是StreamBuilder的位置,但这只是使所有StreamBuilders重建。仅当用户单击“保存”时,如何使它重建?
我已经删除了引用这些项目的代码,以免使人不知所措。
class _ProfileDataState extends State<ProfileData> {
final _formKey = GlobalKey<FormState>();
final FirebaseAuth _auth = FirebaseAuth.instance;
final CollectionReference userCollection =
Firestore.instance.collection('users');
String _uid;
var listType;
// birth date
DateTime _birthDate = DateTime.now();
String _calculatedAge;
TextEditingController birthDateController = TextEditingController();
Future<void> getCurrentUser() async {
final FirebaseUser user = await _auth.currentUser();
setState(() {
_uid = user.uid;
});
}
@override
void initState() {
super.initState();
getCurrentUser();
}
int calculateAge(DateTime birthDate) {
DateTime currentDate = DateTime.now();
int age = currentDate.year - birthDate.year;
int month1 = currentDate.month;
int month2 = birthDate.month;
if (month2 > month1) {
age--;
} else if (month1 == month2) {
int day1 = currentDate.day;
int day2 = birthDate.day;
if (day2 > day1) {
age--;
}
}
return age;
}
Widget profileAgeCalculator(
DateTime listType, String age, String labelText, String dbLabel) {
return Card(
child: ListTile(
dense: true,
title: Text('My ${UIHelper.capitalize(labelText)}:',
style: TextStyle(color: UIHelper.titleColor(context))),
subtitle: Text(_calculatedAge,
style: TextStyle(color: UIHelper.subTitleColor(context))),
trailing: Icon(
Icons.edit,
color: Theme.of(context).primaryColor,
size: 18,
),
contentPadding:
EdgeInsets.only(left: 20.0, top: 2.0, right: 22.0, bottom: 2.0),
onTap: () async {
AlertDialog alertDialog = AlertDialog(
title: Text('Update ${UIHelper.capitalize(labelText)}:'),
content: Padding(
padding: const EdgeInsets.only(top: 15.0, bottom: 15.0),
child: SizedBox(
height: 200,
child: CupertinoTheme(
data: CupertinoThemeData(
textTheme: CupertinoTextThemeData(
dateTimePickerTextStyle: TextStyle(
fontSize: 16,
),
),
),
child: CupertinoDatePicker(
initialDateTime: listType,
mode: CupertinoDatePickerMode.date,
maximumDate: DateTime.now(),
onDateTimeChanged: (dateTime) {
setState(() {
listType = dateTime;
age = calculateAge(dateTime).toString();
});
},
),
),
),
),
actions: <Widget>[
FlatButton(
child: Text(
"CANCEL",
style: TextStyle(color: UIHelper.tardisBlue),
),
onPressed: () {
Navigator.of(context, rootNavigator: true).pop();
},
),
FlatButton(
child:
Text("SAVE", style: TextStyle(color: UIHelper.tardisBlue)),
onPressed: () async {
FocusScope.of(context).unfocus();
await userCollection.document(_uid).updateData({
'$dbLabel': listType,
});
Navigator.of(context, rootNavigator: true).pop();
},
),
],
);
showDialog(
context: context,
builder: (context) {
return alertDialog;
},
);
},
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder(
stream: userCollection.document(_uid).snapshots(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
// Uncompleted State
case ConnectionState.none:
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
break;
default:
// Completed with error
if (snapshot.hasError) return Text(snapshot.error.toString());
// Completed with data
var userDocument = snapshot.data;
if (userDocument["birthDate"] == null) {
_birthDate = DateTime.now() ?? '(Choose One)';
} else {
_birthDate =
userDocument["birthDate"].toDate() ?? DateTime.now();
}
_calculatedAge =
calculateAge(_birthDate).toString() ?? '(Add Your Age)';
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
},
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
profileAgeCalculator(
_birthDate, _calculatedAge, 'age', 'birthDate'),