应用栏和 ListView.length

AppBar and ListView.length

AppBartitle: 是文本。 如果 Body 有 ListView 是由 Stream 制作的。 标题中的文本如何反映ListView项数。

    build(BuildContext context) {
      return Scaffold(
      appBar:AppBar(title: generateTitle()) // <-- how to pass the snapshot.requiredData.length into here?
      body: StreamBuilder(
        stream: theStream();
        builder:(BuildContext context, AsyncSnapshot<List<AnObject>> snapshot) {
          return ListView.builder(
            itemCount: snapshot.requireData.length,            
            itemBuilder: (context, index) =>
              CardFromAnObject(snapshot,snapshot.requireData[index], context),
          )
        }
      )
   )
}

您可以向 addPostFrameCallback 寻求帮助并更新计数。我在这个例子中使用了 counterStream。

class _TSCState extends State<TSC> {
  var counterStream =
      Stream<int>.periodic(const Duration(seconds: 1), (x) => x).take(15);

  int? itemsCount;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: itemsCount != null
              ? Text("total $itemsCount")
              : Text("loading") // null // or use others expression
          ),
      body: StreamBuilder<int>(
        stream: counterStream,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            WidgetsBinding.instance!.addPostFrameCallback((timeStamp) {
              setState(() {
                itemsCount = snapshot.data!;
              });
            });
            return ListView.builder(
              itemCount: snapshot.data!,
              itemBuilder: (context, index) => ListTile(
                title: Text("Item $index"),
              ),
            );
          } else {
            //handle others state
            return CircularProgressIndicator();
          }
        },
      ),
    );
  }
}

我使用 Yeasin Sheikh 的示例代码实现了我的建议。

因为流生成器在示例代码中生成了一个int值,
我用 'snapshot.requiredData' 而不是 'snapshot.requiredData.length'.

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: TSCState(),
    );
  }
}

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

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

class _TSCStateState extends State<TSCState> {
  var counterStream =
      Stream<int>.periodic(const Duration(seconds: 1), (x) => x).take(15);

  int itemsCount;
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<int>(
      stream: counterStream,
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return Scaffold(
            appBar: AppBar(
              title: Text("total ${snapshot.requireData}"),
            ),
            body: ListView.builder(
              itemCount: snapshot.data,
              itemBuilder: (context, index) => ListTile(
                title: Text("Item $index"),
              ),
            ),
          );
        } else {
          return Scaffold(
            appBar: AppBar(title: Text("total")),
            body: CircularProgressIndicator(),
          );
        }
      },
    );
  }
}

您可以添加addPostFrameCallback来统计您的数据项,然后在Appbar中使用totalItem。

    build(BuildContext context) {
      return Scaffold(
      appBar:AppBar(title: generateTitle())
      body: StreamBuilder(
        stream: theStream();
        builder:(BuildContext context, AsyncSnapshot<List<AnObject>> snapshot) {

              if (latchRefresher != snapshot.requireData.length){//init the field on declare to latchRefresher =-1
                                      SchedulerBinding.instance
                                          .addPostFrameCallback((_) => setState(() {
                                        totalItem = snapshot.data.length;
                                       latchRefresher = snapshot.requireData.length;//this will cause only on change to request a refresh
                                      }));
              }
          return ListView.builder(
            itemCount: snapshot.requireData.length,            
            itemBuilder: (context, index) =>
              CardFromAnObject(snapshot,snapshot.requireData[index], context),
          );
        }
      ));}

您可以使用另一个 StreamBuilder 包装 AppBar 标题 属性,然后在流“theStream”结束时更新它。

我上传了关于这个要点的示例代码:https://gist.github.com/Alvarocda/140bbafb7eb24441ba9612a8ccf068ad

基本上,虽然 _appBarCountStreamController 在流上具有空值,但您的应用栏将显示 'Loading'。

当您的流 'theStream' 运行时,您将列表的长度添加到 __appBarCountStreamController,它将仅重建应用栏标题。

不要忘记在 dispose 方法上关闭 _appBarCountStreamController。