В моем приложении есть страница профиля с картами, которые содержат личную информацию. Пользователь щелкает, чтобы открыть AlertDialog, а внутри AlertDialog есть поле для обновления информации из Firestore. В этом случае пользователь выбирает дату рождения из CupertinoDatePicker. Моя проблема в том, что при прокрутке даты страница профиля в фоновом режиме постоянно перестраивается.
Как вы можете из моего кода ниже, я установил это с помощью одного StreamBuilder. Я попытался настроить его так, чтобы каждая карта была 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'),