检索数据时异常:- RenderBox未布局



我正在构建一个具有登录屏幕和注册屏幕的聊天应用程序。经过认证(注册和登录)后,您可以开始与其他用户聊天。我添加了一个控制器属性到我的textField之后,我的代码甚至在删除控制器后崩溃。错误的行没有被提及。只要它开始加载聊天记录,我就会得到一个异常。

渲染库捕获异常

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

RenderBox未布局:RenderRepaintBoundary#7b139 relayoutBoundary=up3 NEEDS-PAINT needs - composition - bits - update
'package:flutter/src/rendering/box。dart':
断言失败:line 1929 pos 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
);
},
);
}
}

不要对TextField使用expanded。用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,
....
)
...

最新更新