SetState 不适用于 listview.builder
Posted
技术标签:
【中文标题】SetState 不适用于 listview.builder【英文标题】:SetState not working with listview.builder 【发布时间】:2021-08-12 04:13:38 【问题描述】:我这里有一些用于应用程序聊天屏幕的代码。这个特定的聊天屏幕用于与机器人聊天。该机器人应该在用户发送每条消息后发送一条消息。机器人要发送的消息列表存储在 messageStrings 中。我正在使用 listview.builder 来使用列表消息中添加的新消息填充 UI。
我正在使用 setstate 添加新消息,但 UI 未使用新消息进行更新。这是我的代码:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../models/chats.dart';
class ReportPage extends StatefulWidget
BuildContext context;
ReportPage(this.context);
@override
_ReportPageState createState() => _ReportPageState();
class _ReportPageState extends State<ReportPage>
@override
Widget build(Object context)
TextEditingController messageContoller = new TextEditingController();
//The first two messages by the bot are already added to the List
List<ChatMessage> messages = [
ChatMessage(messageContent: "Message 1", messageType: "receiver"),
ChatMessage(messageContent: "Message 2", messageType: "receiver"),
];
int messageIndex = 0;
//The next messages that are to be added to the list after a response from the user
List<String> messageStrings = ["Message 3", "Message 4","Message 5",];
return Scaffold(
appBar: AppBar(
title: Row(children: [
Container(
width: 35,
height: 35,
child: Image.asset(
'assets/images/police.png',
fit: BoxFit.cover,
),
decoration:
BoxDecoration(shape: BoxShape.circle, color: Colors.white),
),
SizedBox(
width: 10,
),
Text("CFB bot"),
]),
),
body: Container(
padding: EdgeInsets.all(20),
child: Stack(
children: <Widget>[
ListView.builder(
itemCount: messages.length,
shrinkWrap: true,
padding: EdgeInsets.only(top: 10, bottom: 10),
physics: NeverScrollableScrollPhysics(),
itemBuilder: (context, index)
return Container(
padding:
EdgeInsets.only(left: 14, right: 14, top: 10, bottom: 10),
child: Align(
alignment: (messages[index].messageType == "receiver"
? Alignment.topLeft
: Alignment.topRight),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: (messages[index].messageType == "receiver"
? Colors.grey.shade200
: Colors.blue[200]),
),
padding: EdgeInsets.all(16),
child: Text(
messages[index].messageContent,
style: TextStyle(fontSize: 15),
),
),
),
);
,
),
Align(
alignment: Alignment.bottomLeft,
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
borderRadius: BorderRadius.all(Radius.circular(20))),
padding: EdgeInsets.only(left: 10, bottom: 10, top: 10),
height: 60,
width: double.infinity,
child: Row(
children: <Widget>[
GestureDetector(
onTap: () ,
child: Container(
height: 30,
width: 30,
decoration: BoxDecoration(
color: Colors.lightBlue,
borderRadius: BorderRadius.circular(30),
),
child: Icon(
Icons.add,
color: Colors.white,
size: 20,
),
),
),
SizedBox(
width: 15,
),
Expanded(
child: TextField(
decoration: InputDecoration(
hintText: "Write message...",
hintStyle: TextStyle(color: Colors.black54),
border: InputBorder.none),
controller: messageContoller,
),
),
SizedBox(
width: 15,
),
FloatingActionButton(
onPressed: ()
String message = messageContoller.text;
setState(()
messages.add(ChatMessage(messageContent: message, messageType: "sender"));
messages.add(ChatMessage(messageContent: messageStrings[messageIndex], messageType: "receiver"));
);
messageIndex++;
for(int i = 0; i < messages.length; i++)
print(messages[i].messageContent);
,
child: Icon(
Icons.send,
color: Colors.white,
size: 18,
),
backgroundColor: Colors.blue,
elevation: 0,
),
],
),
),
),
],
),
),
);
【问题讨论】:
【参考方案1】:不要直接使用List.add
,而是尝试将messages
的引用更改为全新的List
,就像这样,
messages = [
...messages,
ChatMessage(messageContent: message, messageType: "sender"),
ChatMessage(messageContent: messageStrings[messageIndex], messageType: "receiver")
];
为什么这样做是因为现在,您正在销毁 messages
的旧引用并为其分配一个全新的 List
引用。
【讨论】:
感谢您的回答。我试过了,它仍然没有更新 UI。有没有其他方法可以解决这个问题? 这是不可能的。 所以你是说,即使你改变了 setState 中的任何东西,你的 UI 也不会重建? 在您的构建函数中添加print
语句以检查它是否被调用。
对不起伙计,问题是我把列表放在了构建函数中。因此,它每次都被重置。我把它放在 State Class 中,现在它工作正常。感谢您的帮助以上是关于SetState 不适用于 listview.builder的主要内容,如果未能解决你的问题,请参考以下文章
this.setState 不适用于 react-native 中的多个文本输入
getCurrentPosition 中的 React-native-maps setState 不适用于我的 url API
Flutter - 另一个 Listview 中的 Listview.builder