0

我正在设计 UI 和动画和其他东西,但是当我开始添加两个StreamBuilders列表视图,使用 Firestore,到 UI 替换虚拟数据时,动画从黄油般的平滑变成了太迟钝我宁愿没有他们在那里.

我正在使用两个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 上都有相同的效果。

4

1 回答 1

1

除了使用流构建器,您还可以使用侦听器来侦听 Firestore 数据库的更新,并在您有更新时使用 setState。出于某种原因,它对我来说效果更好。在你的情况下,这将是这样的:

List<DocumentSnapshot> posts;
var query = Firestore.instance
    .collection('posts')
    .where('userId', isEqualTo: userId);

listener() async {
  query.snapshots().listen((querySnapshot) {
    querySnapshot.documentChanges.forEach((changes) {
      if (posts.every((f) => f != changes.document)) {
        setState(() {
          posts.add(changes.document);
        });
      } else {
        setState(() {
          posts[posts.indexWhere((f) =>
                  f.data['postId'] == changes.document.data['postId'])] =
              changes.document;
        });
      }
    });
  });
}

当然,您必须根据需要调整所有数据。

于 2019-08-31T03:20:03.857 回答