Flutter ListView.builder 插入后不更新
Flutter ListView.builder not updating after insert
我有一个从中查询数据的 SQLite 数据库。根据这些数据,我创建了必要的小部件并将它们存储在列表中。将列表传递给 ListView.builder 我从列表中创建项目。一切看起来都很好,除了我向小部件列表添加新数据时。如果我使用 insert
,则不会显示任何内容。如果我使用 add
就没有问题。这是片段。
List<MessageItem> _messageItems = <MessageItem>[];
// Reads the data and creates the widgets (all OK here)
// Called when reading the data <<<
_readDBMessages() async {
List<Map> messages = await readMessages(_threadID);
List<MessageItem> holderList = <MessageItem>[];
for (final msg in messages) {
holderList.add(new MessageItem(
msg['message'],
msg['timestamp'],
msg['status'],
_contactData['photo']));
}
_messageItems.clear();
setState(() {
_messages = msges;
_messageItems = holderList;
});
}
// When I use _messageItems.add(new MessageItem()); the item shows as expected but it
// it's located on top of the list. Since my ListView is reverse
// I instead use _messagesInsert(0, new MessageItem()); in doing so
// The list is not updated. Scrolling up/down will than proceed to
// show the item as expected.
// Called when storing the data <<<
_storeNewMessage(String message) {
int timestamp = new DateTime.now().millisecondsSinceEpoch;
storeMessage(_threadID, message, _me, 'sending', timestamp, 'text').then((onValue) {
// _readDBMessages();
setState(() {
_messageItems.add(
new MessageItem(
message, timestamp, 'sending', null
)
);
print('Message inserted ---------------');
});
});
}
// Here's my listView constructor <<<
new Expanded(
child: new ListView.builder(
reverse: true,
padding: const EdgeInsets.all(12.0),
itemCount: (_messageItems == null) ? 0 : _messageItems.length,
itemBuilder: (context, i) => _messageItems[i]
)
),
根据 Flutter 医生的说法,一切正常,感谢您的帮助 ;-)
也许您应该将唯一的密钥传递给您的 MessageItem
。
当您收到数据时:
new MessageItem(
msg['message'],
msg['timestamp'],
msg['status'],
_contactData['photo'],
key: Key(msg['message']+msg['timestamp'].toString())
)
添加新条目时:
_messageItems.add(
new MessageItem(
message, timestamp, 'sending', null, key: Key("${message}${timestamp}")
)
);
在MessageItem
构造函数中:
MessageItem(..., {Key key}): super(key: key);
另一种方法是为列表指定一个随机键,像这样:
child: new ListView.builder(
key: new Key(randomString()),
您可以阅读 https://flutter.io/widgets-intro/#keys 中的键或查看 Dismissible
小部件作为示例
我在使用 StreamBuilder 收听 Floor db 更改时遇到了类似的问题,其中 StreamBuilder 正在做出反应,但 ListView 没有得到更新。试过上面的解决方法
child: new ListView.builder(
key: UniqueKey(),
然后 ListView 使用新数据进行更新,但是有一个问题,在上面的实现中,ListView 被刷新,这对添加新数据非常有效,但是当我更新 db 中的数据或使用 dismissible 删除数据时小部件,ListView 再次刷新并显示第一个元素。
所以我尝试将密钥添加到 itemBuilder 中的每个小部件,它对我有用
ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: array.length,
itemBuilder: (context, index) {
return ListItemWidget(
dao: dao,
item: array[index],
key: UniqueKey(),
);
},
);
我有一个从中查询数据的 SQLite 数据库。根据这些数据,我创建了必要的小部件并将它们存储在列表中。将列表传递给 ListView.builder 我从列表中创建项目。一切看起来都很好,除了我向小部件列表添加新数据时。如果我使用 insert
,则不会显示任何内容。如果我使用 add
就没有问题。这是片段。
List<MessageItem> _messageItems = <MessageItem>[];
// Reads the data and creates the widgets (all OK here)
// Called when reading the data <<<
_readDBMessages() async {
List<Map> messages = await readMessages(_threadID);
List<MessageItem> holderList = <MessageItem>[];
for (final msg in messages) {
holderList.add(new MessageItem(
msg['message'],
msg['timestamp'],
msg['status'],
_contactData['photo']));
}
_messageItems.clear();
setState(() {
_messages = msges;
_messageItems = holderList;
});
}
// When I use _messageItems.add(new MessageItem()); the item shows as expected but it
// it's located on top of the list. Since my ListView is reverse
// I instead use _messagesInsert(0, new MessageItem()); in doing so
// The list is not updated. Scrolling up/down will than proceed to
// show the item as expected.
// Called when storing the data <<<
_storeNewMessage(String message) {
int timestamp = new DateTime.now().millisecondsSinceEpoch;
storeMessage(_threadID, message, _me, 'sending', timestamp, 'text').then((onValue) {
// _readDBMessages();
setState(() {
_messageItems.add(
new MessageItem(
message, timestamp, 'sending', null
)
);
print('Message inserted ---------------');
});
});
}
// Here's my listView constructor <<<
new Expanded(
child: new ListView.builder(
reverse: true,
padding: const EdgeInsets.all(12.0),
itemCount: (_messageItems == null) ? 0 : _messageItems.length,
itemBuilder: (context, i) => _messageItems[i]
)
),
根据 Flutter 医生的说法,一切正常,感谢您的帮助 ;-)
也许您应该将唯一的密钥传递给您的 MessageItem
。
当您收到数据时:
new MessageItem(
msg['message'],
msg['timestamp'],
msg['status'],
_contactData['photo'],
key: Key(msg['message']+msg['timestamp'].toString())
)
添加新条目时:
_messageItems.add(
new MessageItem(
message, timestamp, 'sending', null, key: Key("${message}${timestamp}")
)
);
在MessageItem
构造函数中:
MessageItem(..., {Key key}): super(key: key);
另一种方法是为列表指定一个随机键,像这样:
child: new ListView.builder(
key: new Key(randomString()),
您可以阅读 https://flutter.io/widgets-intro/#keys 中的键或查看 Dismissible
小部件作为示例
我在使用 StreamBuilder 收听 Floor db 更改时遇到了类似的问题,其中 StreamBuilder 正在做出反应,但 ListView 没有得到更新。试过上面的解决方法
child: new ListView.builder(
key: UniqueKey(),
然后 ListView 使用新数据进行更新,但是有一个问题,在上面的实现中,ListView 被刷新,这对添加新数据非常有效,但是当我更新 db 中的数据或使用 dismissible 删除数据时小部件,ListView 再次刷新并显示第一个元素。
所以我尝试将密钥添加到 itemBuilder 中的每个小部件,它对我有用
ListView.builder(
padding: const EdgeInsets.all(8),
itemCount: array.length,
itemBuilder: (context, index) {
return ListItemWidget(
dao: dao,
item: array[index],
key: UniqueKey(),
);
},
);