Я разрабатывал пользовательский интерфейс во флаттере, с анимацией и прочим, но когда я начал добавлять два StreamBuilders
со списками, используя Firestore, в пользовательский интерфейс заменили фиктивные данные, анимация превратилась из маслянисто-гладкой в ооочень медленную, я бы предпочел их не иметь там.
Я использую два AnimationControllers
два элемента управления двумя типами анимации, я использовал это руководство, чтобы узнать, как это сделать без setStates
, и он работал гладко, пока я не добавил StreamBuilders
.
Один AnimationController
анимирует переход затухания, а другой - вертикальное перемещение, чтобы скрыть виджет списков с экрана.
Код:
AnimationController _fadeAnimationController;
AnimationController _margAnimationController;
@override
void initState() {
super.initState();
this._fadeAnimationController = AnimationController(
value: 1.0,
duration: Duration(milliseconds: 300),
reverseDuration: Duration(milliseconds: 300),
vsync: this,
);
this._margAnimationController = AnimationController(
value: 0.0,
upperBound: widget.deviceHeight,
duration: Duration(milliseconds: 300),
reverseDuration: Duration(milliseconds: 300),
vsync: this,
);
}
@override
void dispose() {
super.dispose();
this._fadeAnimationController.dispose();
this._margAnimationController.dispose();
}
@override
Widget build(BuildContext context) {
return Material(
color: Colors.black,
child: Stack(
children: <Widget>[
FadeTransition( // FIRST ANIMATED WIDGET
opacity: this._fadeAnimationController,
child: Container(color: Config.pColor),
),
// Other unrelated widgets…
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: <Widget>[
Platform.isIOS
? CupertinoNavigationBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.transparent,
border: Border.all(color: Colors.transparent, width: 0.0, style: BorderStyle.none),
middle: Text('Dost', style: TextStyle(color: Config.bgColor)),
trailing: this._cameraIconButton(),
transitionBetweenRoutes: false,
heroTag: 'CameraAppBar')
: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.transparent,
elevation: 0.0,
title: Text('Dost', style: TextStyle(color: Config.bgColor)),
actions: <Widget>[this._cameraIconButton()],
)
]),
Expanded(
child: AnimatedBuilder( // SECOND ANIMATED WIDGET
animation: this._margAnimationController,
builder: (_, child) => Transform.translate(
offset: Offset(0, this._margAnimationController.value),
child: child,
),
child: HomePage( // STREAMBUILDERS ARE INSIDE THIS WIDGET
cUser: InheritedUser.of(context).user,
showCamera: () {
this._openCloseCamera();
},
showPosts: () {
Funcs.popup(context: context, w: CUPostsPage(cUser: InheritedUser.of(context).user));
},
showSettings: () {
Funcs.navigateTo(context: context, w: SettingsPage(), fullscreenDialog: false);
}),
),
)
],
)
],
),
);
}
Виджет HomePage()
в основном содержит список из двух StreamBuilders
, каждый из которых имеет ListView
, один по горизонтали, а другой по вертикали. Оба выглядят очень похожими.
Виджеты StreamBuilder:
class ChatsList extends StatelessWidget {
@override
Widget build(BuildContext context) => StreamBuilder<List<Chat>>(
initialData: InheritedUser.of(context).user.chats,
stream: APIs().chats.chatsStream(cUserID: InheritedUser.of(context).user.userID),
builder: (context, snap) {
User cUser = InheritedUser.of(context).user;
cUser.chats.clear();
cUser.chats = snap.data;
return ListView.builder(
physics: BouncingScrollPhysics(),
shrinkWrap: true,
padding: EdgeInsets.only(top: 0.0),
itemBuilder: (context, index) => ChatItem(chat: cUser.chats[index]),
itemCount: cUser.chats.length);
});
}
И
class AUPostsList extends StatelessWidget {
final ScrollController scrollController;
AUPostsList({this.scrollController});
@override
Widget build(BuildContext context) => StreamBuilder<List<Post>>(
initialData: [],
stream: APIs().posts.auPostsStream(cUserID: InheritedUser.of(context).user.userID),
builder: (context, snap) {
Map<String, List<Post>> _posts = {};
List<String> _postsUserIDs = [];
snap.data.forEach((post) {
if (_posts[post.user.documentID] == null) {
_posts[post.user.documentID] = [post];
} else {
_posts[post.user.documentID].add(post);
}
if (!_postsUserIDs.contains(post.user.documentID)) {
_postsUserIDs.add(post.user.documentID);
_posts[post.user.documentID].sort((a, b) => b.createdAt.compareTo(a.createdAt));
}
});
return Container(
height: ((MediaQuery.of(context).size.width - 80.0) / 3) * 1.5,
child: ListView.separated(
scrollDirection: Axis.horizontal,
controller: this.scrollController,
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
padding: EdgeInsets.only(top: 0.0, left: 10.0, right: 10.0),
itemBuilder: (context, index) => AUPostItem(posts: _posts[_postsUserIDs[index]]),
separatorBuilder: (context, index) => Container(),
itemCount: _postsUserIDs.length,
));
});
}
Когда я комментирую один из StreamBuilders
, он просто тормозит, однако второй, AUPostsList, намного медленнее, чем ChatsList. Но когда показываются оба, то анимация действительно очень отстает в режиме выпуска, а не в режиме отладки. И оба закомментированы, тогда это оооочень гладко как в режиме отладки, так и в режиме выпуска.
Да, и на iOS, и на Android эффекты одинаковые.