【问题标题】:How to use StreamBuilder inside CustomScrollWidget?如何在 CustomScrollWidget 中使用 StreamBuilder?
【发布时间】:2020-12-19 09:02:46
【问题描述】:

我正在尝试显示来自 sqlite 的一些数据,一切正常,但我不能在 CustomScrollView 中使用 StreamBuilder,它说:

RenderViewport 需要一个 RenderSliv​​er 类型的子级,但接收到一个类型为子级 渲染定位框。

然后我用 SliverPadding 包裹了 StreamBuilder(通常 SliverPadding 被 StreamBuilder 包裹)但是这次它说:

RenderSliv​​erPadding 需要一个 RenderSliv​​er 类型的子级,但收到了一个子级类型 渲染定位框。

我尝试使用 SliverToBoxAdapter 并用它包装 StreamBuilder 但没有解决我的问题,那么我该如何实现呢?

这是我的代码的最后状态:

CustomScrollView(
  slivers: <Widget>[
    SliverAppBar(
      centerTitle: true,
      floating: false,
      snap: false,
      pinned: false,
      expandedHeight: 0,
      elevation: 3,
      forceElevated: true,
      backgroundColor: Theme.of(context).scaffoldBackgroundColor,
      brightness: Brightness.light,
      title: Text(
        'Your Lists',
        style: GoogleFonts.openSans(
            fontSize: 22, fontWeight: FontWeight.bold, color: Colors.black),
      ),
    ),
    SliverPadding(
      padding: EdgeInsets.fromLTRB(16, 16, 16, 74),
      sliver: StreamBuilder<List<Category>>(
          stream: bloc.getAll().asStream(),
          builder: (context, AsyncSnapshot<List<Category>> snapshot) {
            if (snapshot.hasData) {
              return SliverGrid(
                delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                  if (index == snapshot.data.length) {
                    return ListAddCard();
                  }
                  return ListCard(
                    category: snapshot.data[index],
                  );
                }, childCount: snapshot.data.length + 1),
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 2,
                    mainAxisSpacing: 16,
                    crossAxisSpacing: 16,
                    childAspectRatio: 1.1),
              );
            }
            return Center(child: CircularProgressIndicator());
          }),
    )
  ],
);

【问题讨论】:

  • 使用builder作为customscrollview的父级
  • 感谢@pskink,它起作用了,但这个解决方案效率低下吧?因为您重新渲染所有 CustomScrollView 但我只想重新渲染 slivergrid。有没有更有效的方法来实现这一点?
  • 您的流多久发出一次新值?每一秒?每秒十次?更快?
  • 顺便说一句,另一个订单也可以:child: CustomScrollView( slivers: [ SliverToBoxAdapter(child: Container(color: Colors.red, child: Text('header')),), SliverToBoxAdapter( child: StreamBuilder&lt;Object&gt;( stream: Stream.periodic(Duration(seconds: 3), (i) =&gt; 'text $i'), builder: (context, snapshot) { return Container( height: 100, color: Colors.green, child: Text(snapshot.data ?? 'waiting...', textScaleFactor: 2,), ); } ), ), SliverToBoxAdapter(child: Container(height: 1000, color: Colors.blue, child: Text('footer')),), ], ),
  • @pskink 添加新类别或删除或重命名时。感谢其他解决方案。

标签: flutter flutter-sliver stream-builder


【解决方案1】:

解决方案是您应该将整个 CustomScrollView 包装在 Streambuilder 中,而不是反过来。在我使用这种策略之前,我一直面临着同样的问题。

【讨论】:

  • 或者您可以尝试将 ListAddCard() 和 ListCard() 包装在 SliverToBoxAdapter 中,因为它们可能是导致错误的小部件,因为它们可能不是 Sliver。
【解决方案2】:

这里的问题是SliverPadding 需要RenderSliverPadding,但你给它的是RenderPositionedBox。您可以做的是删除 SliverPadding 并将其包装在 SliverGrid 而不是 StreamBuilder 中。
试试这个:

StreamBuilder<List<Category>>(
          stream: bloc.getAll().asStream(),
          builder: (context, AsyncSnapshot<List<Category>> snapshot) {
            if (snapshot.hasData) {
              return  SliverPadding(
      padding: EdgeInsets.fromLTRB(16, 16, 16, 74),
      sliver: SliverGrid(
                delegate: SliverChildBuilderDelegate(
                    (BuildContext context, int index) {
                  if (index == snapshot.data.length) {
                    return ListAddCard();
                  }
                  return ListCard(
                    category: snapshot.data[index],
                  );
                }, childCount: snapshot.data.length + 1),
                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                    crossAxisCount: 2,
                    mainAxisSpacing: 16,
                    crossAxisSpacing: 16,
                    childAspectRatio: 1.1),),
              );
            }
            return Center(child: CircularProgressIndicator());
          }),

【讨论】:

  • 感谢您的回复,但我尝试了您的解决方案,但没有成功,谢谢 :)
  • A RenderViewport 需要一个 RenderSliv​​er 类型的子级,但收到了一个 RenderPositionedBox 类型的子级。
猜你喜欢
  • 2022-12-25
  • 2019-11-29
  • 2021-03-03
  • 2021-05-17
  • 2019-01-05
  • 2021-08-27
  • 2019-12-06
  • 2020-12-11
  • 1970-01-01
相关资源
最近更新 更多