【问题标题】:Exception while retrieving the data :- RenderBox was not laid out检索数据时出现异常:- 未布置 RenderBox
【发布时间】:2021-11-24 07:18:18
【问题描述】:

我正在构建一个带有登录屏幕和注册屏幕的聊天应用程序。验证它(注册和登录)后,您可以开始与其他用户聊天。我在我的 textField 中添加了一个控制器属性,之后我的代码即使在删除控制器后也会崩溃。没有提到错误的行。一旦它开始加载聊天,我就会遇到异常。

渲染库捕获的异常

在 performLayout() 期间抛出了以下断言:

RenderBox 未布置:RenderRepaintBoundary#7b139 relayoutBoundary=up3 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
断言失败:第 1929 行第 12 行:'hasSize'

断言表明框架本身存在错误,或者我们应该在此错误消息中提供更多信息,以帮助您确定和修复根本原因。

这是我的代码:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flashchat1/constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
final _fireStore = FirebaseFirestore.instance;//an instance of fireBase store that stored data created
final _auth = FirebaseAuth.instance;//instance/object of fireBase auth that authorizes users is created
class ChatScreen extends StatefulWidget {
  static String id='Chat_Screen';
  @override
  _ChatScreenState createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  final messageTextController = TextEditingController();
  late User loggedInUser;//LoggedInUser is of type FireBase user(now changed to user)
  late String messageText;
  @override
  void initState()
  {
    super.initState();
    getCurrentUser();//calling the getCurrentUser
  }
  void getCurrentUser()
  async{
    try
    {
      final user= await _auth.currentUser;//get the current user id/name/email.Also currentUser return a future so make it async by adding await and async keywords
      if(user!=null)
      {
        loggedInUser=user ;//LoggedInUser = user contains email of the info
        print(loggedInUser.email);
      }

    }
    catch(e)
    {
      print(e);
    }
  }// Under collection there is documents.Inside documents there are fields like type ,values etc.These fields contain our information
    Future<void> messageStream()//Using a stream it becomes very easy .U just need to click once after you run the app .Then u will be done.
    async {//The snapShot here is FireBase's Query SnapShot
      await for(var snapshot in _fireStore.collection('messages').snapshots()){//make a variable snapshot to store the entire items of the collection in fireBase (Look at the fireBase console there is a collection called messages).This collection takes the snapshot of all the iteams (not literal snapshot .Think it like a snapShot)
        for(var message in snapshot.docs)//make a variable message to access the snapShot.docs .(docs stands for Documentation.Look at the fireBase console)
        print(message.data());
      }
    }
  void getMessages()//(The problem with this is that we need to keep clicking on the onPressed button every single time the new message is sent .So it is not convinient
  async {
    final messages = await _fireStore.collection('messages').get();//to retrieve the data from fire base we are creating a variable message
   messages.docs;//retreive the data from document section under the collection in firestore
    for(var message in messages.docs)//since it is a messages.docs is a list we need to loop through it
       {
        print(message.data());//print the data its messge.data()
     }
  }
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: null,
        actions: <Widget>[
          IconButton(
              icon: Icon(Icons.close),
              onPressed: () {
                messageStream();
                //_auth.signOut();
                //Navigator.pop(context);
                //Implement logout functionality
              }),
        ],
        title: Text('⚡️Chat'),
        backgroundColor: Colors.lightBlueAccent,
      ),
      body: SafeArea(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: <Widget>[
            MessagesStream(),
            Container(
              decoration: kMessageContainerDecoration,
              child: Row(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  Expanded(
                    child: TextField(
                      controller:messageTextController,//add a controller to control the textField
                      onChanged: (value) {
                        messageText=value;//Whatever you chat will be stored in the variable String variable messageText
                      },
                      decoration: kMessageTextFieldDecoration,
                    ),
                  ),
                  FlatButton(
                    onPressed: () {
                      messageTextController.clear();
                      _fireStore.collection('messages').add({
                        'text': messageText,//add the messages sent to fireStore under the messages object that we created manually
                        'Sender': loggedInUser.email,//add the current users email to the sender field
                      },);
                    },//goal is to send the data that we type here to the fireStore cloud
                    child: Text(
                      'Send',
                      style: kSendButtonTextStyle,
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class MessageBubble extends StatelessWidget {
MessageBubble({required this.sender,required this.text});
  final String sender;
  final String text;
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(10.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.end,
        children: [
          Text(sender,
          style:TextStyle(
            fontSize:12.0,
            color:Colors.black54,
          )
          ),
          Material(
            borderRadius: BorderRadius.circular(20.0),
            elevation: 5.0,
            color:Colors.lightBlueAccent,
            child: Padding(
              padding: const EdgeInsets.symmetric(vertical:10.0,horizontal: 20.0),
              child: Text('$text',
                style:TextStyle(
                  color:Colors.white,
                  fontSize:15,
                ),
              ),
            ),
          ),
        ],
      ),
    );;
  }
}

class MessagesStream extends StatelessWidget {
  const MessagesStream({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream:_fireStore.collection('messages').snapshots(),
      builder: (context, AsyncSnapshot snapshot) {
        if(!snapshot.hasData){//flutters async snapshot contains a query snapshot
          return Center(
            child:CircularProgressIndicator(
              backgroundColor:Colors.lightBlueAccent,
            ),
          );
        }
        final messages = snapshot.data.docs;
        List<MessageBubble> messageBubbles = [];//messageBubbles is of the type MessageBubble
        for(var  message in messages)//Loop through the messages
            {
          final messageText = message.data()['text'];//retrieve the data under the text field in message collection
          final messageSender = message.data()['Sender'];//retrieve the data under the Sender field in message collection
          final messageBubble =MessageBubble(sender: messageSender, text: messageText,);
          messageBubbles.add(messageBubble);//add the text to the List messageWidget
        }
        return ListView(//changed from Column to ListView as we want to scroll down .Or else only finite messages can be fit
          children: messageBubbles,//if u don't write else with a return it will show an error as null returned and null safety broken
        );
      },
    );
  }
}

【问题讨论】:

    标签: firebase flutter dart flutter-layout flutter-dependencies


    【解决方案1】:

    不要对TextField 使用扩展。用SizedBox 包裹TextField 并明确地给它一个像这样的高度和宽度,

    ...
    SizedBox(
      width: 200, // a finite number 
      height: 60 // adjust to need
      child: TextField(
        controller:messageTextController,//add a controller to control the textField
        onChanged: (value) {
          messageText=value;//Whatever you chat will be stored in the variable String variable messageText
        },
        decoration: kMessageTextFieldDecoration,
      ),
    ),
    ...
    

    我还注意到您使用了ListView,如果上述方法不起作用,请将shrinkWrap 设置为ListView 的真值

    ...
    ListView(
      shrinkWrap: true,
      ....
    )
    ...
    

    【讨论】:

    • 错误还是来了。
    • @KarthikKK,试着给宽度一个有限的数字,而不是double.infinity。如果它仍然不起作用,请尝试我更新的答案。
    • 错误仍然出现'RenderBox 未布置:RenderPadding#ba040 relayoutBoundary=up1 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE'。但我现在可以查看消息
    • 现在我想我无法在按钮离开屏幕时发送消息
    • resizeToAvoidBottomInset: false 添加到您的Scaffold()
    猜你喜欢
    • 1970-01-01
    • 2023-01-24
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 2019-03-14
    • 1970-01-01
    • 1970-01-01
    • 2022-07-26
    相关资源
    最近更新 更多