Flutter ListView在滚动一段距离后如何保持活动状态

27

我想要让已经在ListView中呈现的小部件保持活动状态keepAlive。我尝试了使用ListView类提供的addAutomaticKeepAlives:true属性。

这是我使用的示例代码。同样的问题也出现在SliverList提供的SliverChildBuilderDelegate委托中。

ListView.builder(
    itemBuilder: (context,index){
      return Card(
        child: Container(
          child: Image.asset("images/${index+1}.jpg",fit: BoxFit.cover,),
          height: 250.0,
        ),
      );
    },
    addAutomaticKeepAlives: true,
    itemCount:40 ,
);
4个回答

48

为了使automaticKeepAlive生效,需要保持存活的每个项都必须发送特定的通知。

触发此类通知的典型方法是使用AutomaticKeepAliveClientMixin

class Foo extends StatefulWidget {
  @override
  FooState createState() {
    return new FooState();
  }
}

class FooState extends State<Foo> with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    return Container(

    );
  }

  @override
  bool get wantKeepAlive => true;
}

3
这对图片有效吗?我尝试过,但当我滚动时,图像仍会重新渲染。如果缓慢滚动,则没有问题。但是在快速滚动中,图像小部件会重新渲染。 - NIRAV PATEL
1
你好,你能帮忙吗?我在使用CustomScrollView和SliverList时遇到了类似的问题...当页面滚动时,我的WebView会不断重新加载...我已经将cacheExtent设置得足够高了。我还有所有的前提条件,比如:super.build(context);bool get wantKeepAlive覆盖...我还设置了AutomaticKeepAliveClientMixin...不确定发生了什么事,但是在像SingleChildScrollView这样的东西中,WebView肯定不会重新加载..所以我猜测是CustomScrollView/SliverList导致了它的销毁.. - Chris
谢谢您,即使我已经阅读了https://api.flutter.dev/flutter/widgets/ListView-class.html,我也没有意识到它在最后一点中提到了! - Sebastian

25

根据AutomaticKeepAliveClientMixin和Remi的回答,子类必须实现wantKeepAlive方法,并且他们的构建方法必须调用super.build(返回值总是null,应该被忽略)。

因此,请将您的build方法更改为:

class Foo extends StatefulWidget {
  @override
  FooState createState() {
    return new FooState();
  }
}

class FooState extends State<Foo> with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Container(

    );
  }

  @override
  bool get wantKeepAlive => true;
}

2
super.build(context); 真的解决了我的问题。谢谢! - DVegasa
在超类型中,“build”方法始终是抽象的。 - metamonkey
我得到了相同的结果。似乎你不能再从状态中调用这个方法了... - shawnblais

10

你也可以尝试查看listview builder的cacheExtent属性。将其设置为覆盖你的项目所需的值将保持它们全部处于活动状态。

感谢上面的Remi。我之前并不知道在列表上使用时需要保持项目处于活动状态 - 这在flutter文档中以前没有提到...


6
如果您想保持一个slivers列表(用于CustomScrollView)的活性,您只需要使用'SliverChildListDelegate'而不是'SliverChildBuilderDelegate'。
以下是我的代码:
final List<Product> products;
return CustomScrollView(
  controller: _scrollController,
    slivers: [
      _mySliverAppBar(context, title),
      SliverList(
        delegate: SliverChildListDelegate(
          List.generate(products.length, (index) => _myProductCard(context,products[index]))
        )
        // SliverChildBuilderDelegate(
        //   (context, index) => _myProductCard(context, products[index]),
        //   childCount: products.length,
        // ),
      ),
   ],
);

从代码中可以看出,我之前使用了 SliverChildBuilderDelegate


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接