【问题标题】:How to smoothly update a Flutter AnimatedList without using a GlobalKey.currentState?如何在不使用 GlobalKey.currentState 的情况下平滑更新 Flutter AnimatedList?
【发布时间】:2019-11-15 17:15:59
【问题描述】:

我发现的所有将项目插入 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.of() 调用的上下文不包含 动画列表。

我确信 Flutter 团队已经提供了一种方法来触发 Widget 树外部的更新,我只是不知道如何获得它。也许我的技术不正确。

【问题讨论】:

  • 试过AnimatedList.of静态方法?
  • 我之前曾尝试过,但忘记将其包含在我的问题描述中。我很抱歉。这是我在尝试您的建议时遇到的错误:AnimatedList.of() 使用不包含 AnimatedList 的上下文调用。从传递给 AnimatedList.of() 的上下文开始,找不到任何 AnimatedList 祖先。 ....... docs.flutter.io/flutter/widgets/AnimatedListState-class.html 使用的上下文是:Conversation(dependencies: [MediaQuery, _LocalizationsScope-[GlobalKey#4a807], _InheritedTheme], state: ConversationState#f8474 有什么建议的方法吗?
  • 你传递了错误的上下文 - 你应该使用向上树时会找到 AnimatedList 小部件的上下文 - 参见 implementation 代码 here
  • 谢谢,我看看能不能找出正确的上下文。如果我想通了并且有效,请重新提交您的评论作为答案,我会感谢您。
  • 和? Builder 的上下文效果更好?

标签: flutter flutter-animatedlist


【解决方案1】:

在动画列表小部件中以动画方式引入新项目时,我遇到了同样的问题。尽管看起来很奇怪,但您可以通过检查状态是否仍然为空来解决此问题:

if(animatedListKey.currentState != null)
  animatedListKey.currentState.insertItem(0);

这意味着它不会在重建时尝试插入项目,直到状态可用。试试看。

您可以在此处查看我的教程中的代码:https://github.com/Morthor/flutter_todo_app_talk/blob/youtube_animatedList/lib/main.dart

【讨论】:

    猜你喜欢
    • 2021-06-08
    • 2019-06-19
    • 2015-11-16
    • 2016-04-11
    • 2019-10-24
    • 2021-11-17
    • 2013-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多