如何存储流数据并在颤振列表视图中显示新数据和旧数据?

时间:2021-04-01 05:53:43

标签: android flutter listview dart stream

我正在尝试显示来自 Reddit API 的评论流。我正在使用 Streambuilder 在内容到达时流式传输内容并将其显示为列表视图,这是我只能查看当前流内容,并且随着新流内容出现替换旧内容,这将消失。如果我不提及列表视图中的项目数.builder 无限打印内容仍然出现新流。

有没有办法以可滚动的方式与以前的内容一起显示内容,并在新的流消息出现时自动向下滚动??

1 个答案:

答案 0 :(得分:1)

假设评论流一次返回单个(最好是唯一的)评论而不是列表,您需要做的是将传入的评论存储在状态对象中,例如列表。当新评论通过流时,您将其添加到列表中,然后触发小部件重建。

您现在正在做的是用每个新的流元素替换状态而不是累积它们。使用您提供的代码,我对其进行了编辑,使其充当累加器。注意添加到状态的 List<Comment> comments = <Comment>[] 对象。我还删除了 StreamBuilder,因为这对这个用例没有帮助。

import 'package:flutter/material.dart';
import 'dart:async';
import 'package:draw/draw.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: RedditFlutter(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class RedditFlutter extends StatefulWidget {
  RedditFlutter({Key key}) : super(key: key);

  @override
  _RedditFlutterState createState() => _RedditFlutterState();
}

class _RedditFlutterState extends State<RedditFlutter> {
  var comments;
  ScrollController _scrollController =
      new ScrollController(initialScrollOffset: 50.0);
  List<Comment> comments = <Comment>[];
  StreamSubscription<Comment>? sub;

  var msg = '';
  Future<void> redditmain() async {
    // Create the `Reddit` instance and authenticated
    Reddit reddit = await Reddit.createScriptInstance(
      clientId: 'clientid',
      clientSecret: 'clientsecret',
      userAgent: 'useragent',
      username: 'username',
      password: 'password', // Fake
    );

    // Listen to comment stream and accumulate new comments into comments list
    sub = reddit.subreddit('cricket').stream.comments().listen((comment) {
      if (comment != null) {
        // Rebuild from state when a new comment is accumulated
        setState(() {
          comments.add(comment);
        })
      }
    });
  }

  @override
  void initState() {
    // TODO: implement initState
    redditmain();

    super.initState();
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Reddit"),
        centerTitle: true,
      ),
      body: Center(
        child: Container(
                child: ListView.builder(
                  controller: _scrollController,
                  itemCount: comments.length,
                  itemBuilder: (context, index) {
                    final Comment comment = comments[index];
                    return Card(
                      child: ListTile(
                        leading: Image.asset('assets/criclogo.png'),
                        title: Text(comment.body),
                        trailing: Icon(Icons.more_vert),
                      ),
                    );
                  },
                ),
              );
      ),
    );
  }

  @override
  void dispose() {
    sub?.cancel();
    super.dispose();
  }
}

请注意,我尚未测试此代码,因此可能存在(微不足道的)错误。不过,从概念上讲,它应该没问题。