Flutter 在使用 StreamBuilder 从 firebase 加载数据之前显示红色错误屏幕,如何解决?

Posted

技术标签:

【中文标题】Flutter 在使用 StreamBuilder 从 firebase 加载数据之前显示红色错误屏幕,如何解决?【英文标题】:Flutter show's a red error screen before loading data from firebase using StreamBuilder, how to fix? 【发布时间】:2020-02-11 06:33:10 【问题描述】:

我正在从 firebase 获取数据并使用该数据制作卡片。显示用户的某些数据 从数据库中,数据加载正常,但 1 秒或更长时间出现红色错误屏幕。我希望这个消失我会告诉你我的代码。有人可以帮我看看出了什么问题。我不知道发生这种情况我做错了什么,我得到了错误

在 null 上调用了 getter 'uid'。 接收方:空 尝试调用:uid

在 null 上调用了方法“[]”。 接收方:空 尝试调用:

这是我的代码,任何帮助将不胜感激,谢谢

class CardBuilder extends StatefulWidget 

  final String title;
  final String text;
  final IconData icon;

  CardBuilder(Key key, this.title,this.text,this.icon): super(key: key);

  @override
  _CardBuilderState createState() => _CardBuilderState();


class _CardBuilderState extends State<CardBuilder> 
  FirebaseUser user;
  String error;

  void setUser(FirebaseUser user) 
    setState(() 
      this.user = user;
      this.error = null;
    );
  

  void setError(e) 
    setState(() 
      this.user = null;
      this.error = e.toString();
    );
  

  @override
  void initState() 
    super.initState();
    FirebaseAuth.instance.currentUser().then(setUser).catchError(setError);
  

  @override
  Widget build(BuildContext context) 
    return StreamBuilder(
        stream: Firestore.instance.collection(UserInformation).document(user.uid).snapshots(),
        builder: (context, snapshot) 
          var userDocument = snapshot.data;
          // User userDocument here ..........
          return Card(
              margin: EdgeInsets.only(left: 20,right: 20,top: 20),
              child: ListTile(
                leading:
                Icon(widget.icon, color: QamaiGreen, size: 20.0),
                title: AutoSizeText(
                  '$widget.title :   $userDocument[widget.text]',
                  style: TextStyle(
                      fontFamily: 'Montserrat',
                      fontWeight: FontWeight.w600,
                      color: QamaiThemeColor,
                      fontSize: 15
                  ),
                  maxLines: 1,
                  maxFontSize: 15,
                  minFontSize: 12,
                ),
              ));
        );
  


 

【问题讨论】:

【参考方案1】:

所以在尝试了一些东西之后,我终于修复了这个错误。决定发布答案,因为这个问题在网上没有任何解决方案。至少我找不到一个。希望这可以帮助遇到同样问题的人

我首先做的是声明一个包含 user.uid 值的字符串

String userid;
void _getUser() async 
  FirebaseUser user = await FirebaseAuth.instance.currentUser();
  userid=user.uid;

现在在卡片生成器小部件中,我摆脱了额外的东西,并在初始化状态下简单地调用了 _getUser() 方法

class _CardBuilderState extends State<CardBuilder> 

  @override
  void initState() 
    super.initState();
    _getUser();
  

  @override
  Widget build(BuildContext context) 
    return StreamBuilder(
        stream: Firestore.instance.collection(UserInformation).document(userid).snapshots(),
        builder: (context, snapshot) 
          if(snapshot.hasData)
            
              final userDocument = snapshot.data;
              final title=userDocument[widget.text];
              return Card(
                  margin: EdgeInsets.only(left: 20,right: 20,top: 20),
                  child: ListTile(
                    leading:
                    Icon(widget.icon, color: QamaiGreen, size: 20.0),
                    title: AutoSizeText(
                      '$widget.title :   $title',
                      style: TextStyle(
                          fontFamily: 'Montserrat',
                          fontWeight: FontWeight.w600,
                          color: QamaiThemeColor,
                          fontSize: 15
                      ),
                      maxLines: 1,
                      overflow: TextOverflow.ellipsis,
                      maxFontSize: 15,
                      minFontSize: 9,
                    ),
                  ));
            
          else
            return Card(
                margin: EdgeInsets.only(left: 20,right: 20,top: 20),
                child: ListTile(
                  leading:
                  Icon(widget.icon, color: QamaiGreen, size: 20.0),
                  title: AutoSizeText(
                    'LOADING...',
                    style: TextStyle(
                        fontFamily: 'Montserrat',
                        fontWeight: FontWeight.w600,
                        color: QamaiThemeColor,
                        fontSize: 15
                    ),
                    maxLines: 1,
                    overflow: TextOverflow.ellipsis,
                    maxFontSize: 15,
                    minFontSize: 9,
                  ),
                ));
          

        );
  

最后的更改是添加一个条件检查快照是否有数据。在我的情况下,将特定文档字段保存在最终变量中也有很大帮助

final title=userDocument[widget.text];

最后添加了一个 else 条件来模拟显示加载文本的相同卡片界面。如果你愿意,你可以使用 CirculorIndicator,这也对我有用,这对界面来说看起来更自然。

【讨论】:

【参考方案2】:

您可以在加载数据时显示进度指示器 如下图

return StreamBuilder(
    stream: Firestore.instance.collection(UserInformation).document(user.uid).snapshots(),
    builder: (context, snapshot) 
    //==========show progress============
     if (!snapshot.hasData) 
        return CircularProgressIndicator()            
      
      var userDocument = snapshot.data;
      // User userDocument here ..........

【讨论】:

感谢您的回复,这根本不起作用。对红屏影响为零 Fork 你的问题,你可以加载数据,但是在加载数据之前你会得到一个红屏,你可以使用流构建器初始数据的属性 设置初始数据 虽然我的回答对我来说效果很好 我不知道在初始数据中设置什么,您有什么建议吗?【参考方案3】:

在 main.dart 中试试这个:

void main() async 
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());

【讨论】:

以上是关于Flutter 在使用 StreamBuilder 从 firebase 加载数据之前显示红色错误屏幕,如何解决?的主要内容,如果未能解决你的问题,请参考以下文章

FirebaseStorage + Flutter,streamBuilder?

Flutter:StreamBuilder 快照——无数据

在 Flutter 中使用 streamBuilder 时条件不起作用

如何在 Flutter Web 上使用 StreamBuilder 和 Firestore?

Flutter:Streambuilder 导致 Firestore 上的读取过多

Flutter Refreshindicator 在使用 StreamBuilder 添加新项目后重建 Listview.Builder