我发现的所有将项目插入 Flutter AnimatedList 的示例都使用 GlobalKey.currentState 来告诉 AnimatedList 小部件已插入项目。与从列表中删除相同。
众所周知,在 Flutter 中 GlobalKey 的 currentState 可能为 null。
就我而言,我正在等待 Firebase 消息通过。当消息被插入到 AnimatedList 的列表数据中时,如果要遵循为 AnimatedList 显示的流行示例,则可以使用分配的 GlobalKey.currentState 来告诉 AnimatedList 新项目插入的位置。
但是,就我而言,当我尝试使用它时, GlobalKey.currentState 为空。
否则我可以使用什么?我知道我可以使用 setState 但这会导致完整的小部件刷新,在这种情况下,它会出现在屏幕上,而不是所需的 AnimatedList 插入,它既漂亮又流畅。
许多人都避免使用 InheritedWidget,但如果这是正确的技术,我无法理解在这种情况下如何实现它。
/////////
// NOTE: This is close to real code, but consider it pseudocode since it is a cut and paste from the real code less quite a bit of extra stuff I have in there. It certainly will not compile but it is representative of the issue.
/////////
class Conversation extends StatefulWidget {
Conversation({Key key, @required this.cid, this.notificationsHub}) : super(key: key);
// A bit of a hack here, but my Firebase cloud messages come through this object
MyNotificationsHub notificationsHub;
// a conversation id
final int cid;
@override
ConversationState createState() => ConversationState(cid: this.cid, notificationsHub: notificationsHub);
}
//////////
class ConversationState extends State<Conversation>
with MyNotificationsListener {
ConversationState({Key key, @required this.cid, this.notificationsHub}); // : super(key: key);
MyNotificationsHub notificationsHub;
List<ConversationFeed> feed = List();
// The GlobalKey keeps track of the visible state of the list items
// while they are being animated.
final GlobalKey<AnimatedListState> _listKey = GlobalKey();
///////////
initState() {
notificationsHub.addNotificationsListener(this);
}
///////////
// This is where the issue occurs, when a Firebase message comes in and I attempt to use the GlobalKey the currentState component is null
///////////
void receiveAlert ( MyNotificationItem alert ){
int insertIndex=0;
feed.insert(insertIndex, new ConversationFeed( alert ) );
//******* Issue below, null currentState *******
_listKey.currentState.insertItem(insertIndex);
//******* Issue above, null currentState *******
}
////////////
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Conversation")),
body:
new AnimatedList(
// Give the Animated list the global key
key: _listKey,
initialItemCount: feed.length,
itemBuilder: (context, index, animation) {
return ListTile(
title: Text ( feed[index].getMessageContentsString() );
})
);
}
实际结果是由于 GlobalKey 的 currentState 为空而在运行期间引发空指针错误。
/// 更新:
我尝试了 AnimatedList.of(context) 方法和 Builder 来解决这个问题。我以以下方式尝试过:
// Declared an instance variable of BuildContext in my class definition
BuildContext acontext;
// in the Builder call I assigned it in the following manner:
body: Builder(
builder: (BuildContext zcontext) {
acontext = zcontext ;
return ( AnimatedList (....) ); }
)
// & inside my receiveAlert method I used it in the following manner:
void receiveAlert ( MyNotificationItem alert ){
....
AnimatedList.of(acontext).insertItem(insertIndex);
}
使用上述构造时,出现以下错误:
使用不包含 AnimatedList 的上下文调用 AnimatedList.of()。
我确信 Flutter 团队已经提供了一种触发 Widget 树外部更新的方法,我只是不确定如何获得它。也许我的技术不正确。