Flutter PageView组件怎样让子组件不会重复加载

在做一个美女相册flutter demo app的时候发现,每次切换页面的时候,里面的子页面(GridView widget)每次都会重新加载,就像下面这样:


重新加载

这样的体验肯定不行。经过一番调研后发现竟然还需要做蛮多事情的。

先看看目前的实现:

class BeautyListWidget extends StatefulWidget {
  final int tabIndex;

  const BeautyListWidget({Key key, this.tabIndex}) : super(key: key);
  @override
  _BeautyListWidgetState createState() => _BeautyListWidgetState();
}

class _BeautyListWidgetState extends State<BeautyListWidget> {

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Beauty>>(
      future: getBeautysForTab(widget.tabIndex),
      builder: (BuildContext context, AsyncSnapshot<List<Beauty>> snapshot) {
        var connectionState = snapshot.connectionState;
        if (connectionState == ConnectionState.done && snapshot.hasData) {
          var data = snapshot.data;
          return GridView.builder(
            gridDelegate:
            SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, mainAxisSpacing: 10, crossAxisSpacing: 10, ),
            itemBuilder: (BuildContext context, int index) {
              return FadeInImage.assetNetwork(placeholder: 'assets/loading.png', image: data[index].thumbURL);
            },
            itemCount: data.length,
          );
        } else {
          return Center(
            child: CircularProgressIndicator(
              backgroundColor: Colors.black,
            ),
          );
        }
      },
    );
  }
}

这个就是包含在PageView里面的子组件,很简单,通过FutureBuilder调一个接口返回数据后build一个GridView。很显然每次切换Tab的时候,应该是每次都进入了_BeautyListWidgetState的build方法,导致每次都会重新刷新。那要怎样才能做到加载后切换不再刷新呢?

1、_BeautyListWidgetState实现AutomaticKeepAliveClientMixin

需要实现wantKeepAlive方法(返回true),另外在build方法最前面需要 调用super.build(context);,如下:

class _BeautyListWidgetState extends State<BeautyListWidget> with AutomaticKeepAliveClientMixin<BeautyListWidget> {

  @override
  Widget build(BuildContext context) {
    super.build(context);  //需要调用super
    return /* ... */
  }

  @override
  bool get wantKeepAlive => true;  //需要返回true
}

2、FutureBuilder中的future属性需要是同一个实例

所以你需要在initState方法中创建这个Future。如下:

class _BeautyListWidgetState extends State<BeautyListWidget> with AutomaticKeepAliveClientMixin<BeautyListWidget> {

  Future<List<Beauty>> _future; //保存这个实例

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return FutureBuilder<List<Beauty>>(
      future: _future,  //每次build方法都是同一个实例
      builder: (BuildContext context, AsyncSnapshot<List<Beauty>> snapshot) {
          return /* ... */
        }
      },
    );
  }

  @override
  void initState() {
    super.initState();
    _future = getBeautysForTab(widget.tabIndex);  //创建这个实例
  }

  @override
  bool get wantKeepAlive => true;
}

好了。效果实现了。不过稍后还需要看看AutomaticKeepAliveClientMixin源码,看看它是如何做到的。


保持状态

Reference:https://stackoverflow.com/questions/51224420/flutter-switching-to-tab-reloads-widgets-and-runs-futurebuilder

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容