Ненулевая строка должна быть предоставлена текстовому виджету flutter?

#firebase #flutter

# #firebase #flutter

Вопрос:

Я пытаюсь реализовать проверку, что если user DisplayName имеет значение null в firebase. Он должен перейти к форме, в которой он должен ввести свое имя. В настоящее время DisplayName в firebase по умолчанию имеет значение null . Но я получаю сообщение об ошибке.

Для текстового виджета должна быть предоставлена ненулевая строка.

‘package:flutter/src/widgets/text.dart’:

Неудачное утверждение: строка 360 поз 10: «данные! = null»

 Row(
  children: [
    Container(
      margin: EdgeInsets.only(bottom: 50, left: 30),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        //crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text("Welcome !"),
          // ignore: unrelated_type_equality_checks
          Text(snapshot.data.documents
                      .elementAt(index)['displayName']) !=
                  null
              ? Text(snapshot.data.documents
                  .elementAt(index)['displayName'])
              : Navigator.pushNamed(context, '/UserDetail'),
        ],
      ),
    ),
  ],
),
 

Ответ №1:

Попробуйте это вместо этого.

 Row(
  children: [
    Container(
      margin: EdgeInsets.only(bottom: 50, left: 30),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        //crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text("Welcome !"),
          // ignore: unrelated_type_equality_checks
          snapshot.data.documents.elementAt(index)['displayName'] !=
                  null
              ? Text(snapshot.data.documents
                  .elementAt(index)['displayName'])
              : Navigator.pushNamed(context, '/UserDetail'),
        ],
      ),
    ),
  ],
),
 

Text Виджет вам этого не даст null . Только те данные, которые вы предоставляете, могут быть null

Комментарии:

1. Это сработало, но получить это сейчас. Было выдано следующее утверждение building: setState() или markNeedsBuild(), вызванные во время сборки. Этот виджет наложения не может быть помечен как требующий сборки, поскольку фреймворк уже находится в

2. Куда вы вызываете setState? Покажите весь ваш код

Ответ №2:

Вы многое упускаете. Давайте попробуем это исправить!

  1. Игнорировать возможные ошибки — плохая идея.
  2. Никогда не пишите // ignore: unrelated_type_equality_checks
  3. Что пытается сделать ваш код? Нам нужно знать, что вам нужно.

Что не так с тем, что вы написали?

  1. // ignore: заставляет линтер игнорировать проблему определенного типа. Вы проигнорировали unrelated_type_equality_checks , что означает, что вы не считаете ошибкой сравнивать два разных типа данных. Это нехорошо. 2 и "someString" это разные типы данных. Когда вы сравниваете их: 2 == "someString" он никогда не будет оценивать true . Так будет всегда false .
  2. Фактическое сравнение, которое вы написали, всегда верно.
               Text(snapshot.data.documents
                      .elementAt(index)['displayName']) !=
                  null
              ? Text(snapshot.data.documents
                  .elementAt(index)['displayName'])
              : Navigator.pushNamed(context, '/UserDetail')
 

Вот это сравнение только в одной строке:

 Text(snapshot.data.documents.elementAt(index)['displayName']) != null
 

Давайте упростим это, чтобы показать, что не так. Посмотрите, почему сравнение всегда верно?

 Text('displayName') != null // always true
 

Вы, вероятно, хотели написать: (Я только удалил Text() из сравнения, которое вы написали.)

               snapshot.data.documents
                      .elementAt(index)['displayName'] !=
                  null
              ? Text(snapshot.data.documents
                  .elementAt(index)['displayName'])
              : Navigator.pushNamed(context, '/UserDetail')
 

Но этот код по-прежнему не имеет смысла! Если отображаемое имя документа не было null, Text виджет является результатом сравнения. Если отображаемое имя было null, мы вызываем Navigator.pushNamed which не является функцией, которая возвращает a Widget . Нам нужны обе части тернарного оператора, чтобы возвращать a Widget , и только Text() часть возвращает a Widget . Вызов Navigator.pushNamed не возвращает a Widget , что является ошибкой.

Вот как вы можете исправить это несоответствие типов:

               snapshot.data.documents
                      .elementAt(index)['displayName'] !=
                  null
              ? Text(snapshot.data.documents
                  .elementAt(index)['displayName'])
              : Text("Something went wrong!")
 

Но есть еще одна проблема после того, как мы исправим это несоответствие типов в троичном операторе. Мы повторяемся! snapshot.data.documents.elementAt(index)['displayName'] записывается дважды! Не повторяйтесь

               var name = snapshot.data.documents.elementAt(index)['displayName'];
              name != null
                  ? Text(name)
                  : Text("Something went wrong!")
 

Видите, как мы получаем Text Widget независимо от того, что? Мы можем сократить его!

               var name = snapshot.data.documents.elementAt(index)['displayName'];
              Text(name != null ? name : "Something went wrong!")
 

Эта проверка на нуль настолько распространена, что Dart предоставляет оператору ?? для ее выполнения.

               var name = snapshot.data.documents.elementAt(index)['displayName'];
              Text(name ?? "Something went wrong!")
 

Но в этом коде все еще есть ошибки.

Я должен предположить, что snapshot это имеет тип данных AsyncSnapshot , потому что ваш пример не был завершен. AsyncSnapshot может быть ошибка, и это могут быть данные. Вы должны проверить, прежде чем использовать данные!

               if (snapshot.hasError) return Text("Oops!");

              var name = snapshot.data.documents.elementAt(index)['displayName'];
              Text(name ?? "Something went wrong!")
 

Ожидание получения документа не является ошибкой. Это означает, что нам нужно проверить, есть ли AsyncSnapshot у него данные!

               if (snapshot.hasError) return Text("Oops!");
              if (!snapshot.hasData) return Text("No data yet!");

              var name = snapshot.data.documents.elementAt(index)['displayName'];
              Text(name ?? "Something went wrong!")
 

Отлично! Теперь мы уверены, что в снимке есть данные! Но что, если эти данные представляют собой пустой список?

               if (snapshot.hasError) return Text("Oops!");
              if (!snapshot.hasData) return Text("No data yet!");
              if (snapshot.data.documents.isEmpty) return Text("No documents!");

              var name = snapshot.data.documents.elementAt(index)['displayName'];
              Text(name ?? "Something went wrong!")
 

Но что, если мы получим только один документ в списке документов, и index есть 5 ? Это было бы RangeError . Что делать, если displayName ее нет в документе? Это было бы KeyError .

Если вы уверены, что ваш index файл не будет слишком большим и что все ваши документы имеют a displayName , не стесняйтесь игнорировать возможные ошибки.

Вот что мы получаем, когда исправляем все недоразумения.

               if (snapshot.hasError) return Text("Oops!");
              if (!snapshot.hasData) return Text("No data yet!");
              if (snapshot.data.documents.isEmpty) return Text("No documents!");

              var name = snapshot.data.documents.elementAt(index)['displayName'];
              
              return Row(
                children: [
                  Container(
                    margin: EdgeInsets.only(bottom: 50, left: 30),
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Text("Welcome !"),
                        Text(name ?? "Something went wrong!")
                      ],
                    ),
                  ),
                ],
              );