Как плавно обновить Flutter AnimatedList без использования GlobalKey.currentState?
Все примеры, которые я нашел для вставки элементов во 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() );
})
);
}
Фактические результаты - ошибка нулевого указателя, возникающая во время работы из-за того, что currentKtate 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 предоставила способ запуска обновления, внешнего по отношению к дереву виджетов, я просто не знаю, как к нему добраться. Возможно, мои методы неверны.
0 ответов
У меня была такая же проблема при анимации введения нового элемента в виджет анимированного списка. Как ни странно, вы можете решить эту проблему, проверив, остается ли состояние нулевым:
if(animatedListKey.currentState != null)
animatedListKey.currentState.insertItem(0);
Это означает, что он не будет пытаться вставить элемент во время перестройки, пока состояние не станет доступным. Попробуй это.
Вы можете проверить код из моего руководства здесь: https://github.com/Morthor/flutter_todo_app_talk/blob/youtube_animatedList/lib/main.dart