Как плавно обновить Flutter AnimatedList без использования GlobalKey.currentState? - PullRequest
1 голос
/ 05 июля 2019

Все примеры, которые я нашел для вставки элементов во Flutter AnimatedList, используют GlobalKey.currentState, чтобы сообщить виджету AnimatedList, что элемент был вставлен.То же самое с удалением из списка.

Известно, что в Flutter значение currentState для GlobalKey может быть нулевым.

В моем случае я жду сообщения Firebase, чтобы пройти.Когда кажется, что сообщение вставлено в данные Списка AnimatedList и если нужно следовать распространенным примерам, показанным для AnimatedList, можно использовать назначенный GlobalKey.currentState, чтобы сообщить AnimatedList, где был добавлен новый элемент.

Но, в моем случае, когда я пытаюсь его использовать, GlobalKey.currentState имеет значение null.

Что я могу использовать в противном случае?Я знаю, что могу использовать 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() );
          })
       );
}

Фактические результаты - ошибка нулевого указателя, возникающая во время работы из-за значения currentState в GlobalKey, равного null.

/// Обновления:

Я попробовал метод 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 () вызывается с контекстом, который не содержитanimatedList.

Я уверен, что команда Flutter предоставила способ запуска обновления, внешнего по отношению к дереву виджетов, я просто не знаю, как к нему добраться.Возможно, мои методы неверны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...