Flutter / Dart / Firestore: восстановление StreamBuilder с помощью прокрутки CupertinoDatePicker - PullRequest
0 голосов
/ 25 мая 2020

В моем приложении есть страница профиля с картами, которые содержат личную информацию. Пользователь щелкает, чтобы открыть AlertDialog, а внутри AlertDialog есть поле для обновления информации из Firestore. В этом случае пользователь выбирает дату рождения из CupertinoDatePicker. Моя проблема в том, что при прокрутке даты страница профиля в фоновом режиме постоянно перестраивается.

Gif example of issue

Как вы можете из моего кода ниже, я установил это с помощью одного 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'),


...