FutureBuilder刷新数据的方式

原创
2020/11/05 10:25
阅读数 1K

FutureBuilder刷新数据的方式

源码

///订阅
void _subscribe() {
    if (widget.future != null) {
      final Object callbackIdentity = Object();
      _activeCallbackIdentity = callbackIdentity;
      widget.future.then<void>((T data) {
        if (_activeCallbackIdentity == callbackIdentity) {
          setState(() {
            _snapshot = AsyncSnapshot<T>.withData(ConnectionState.done, data);
          });
        }
      }, onError: (Object error) {
        if (_activeCallbackIdentity == callbackIdentity) {
          setState(() {
            _snapshot = AsyncSnapshot<T>.withError(ConnectionState.done, error);
          });
        }
      });
      _snapshot = _snapshot.inState(ConnectionState.waiting);
    }
  }

  ///取消订阅
  void _unsubscribe() {
    _activeCallbackIdentity = null;
  }

我们发现,想要刷新FutureBuilder的数据,核心方法就是触发他的_subscribe()方法。然后看一下这个方法是在哪里调用的:

@override
  void initState() {
    super.initState();
    _snapshot = AsyncSnapshot<T>.withData(ConnectionState.none, widget.initialData);
    _subscribe();
  }

  @override
  void didUpdateWidget(FutureBuilder<T> oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (oldWidget.future != widget.future) {
      if (_activeCallbackIdentity != null) {
        _unsubscribe();
        _snapshot = _snapshot.inState(ConnectionState.none);
      }
      _subscribe();
    }
  }

由源码所见,只有当FutureBuilder创建的时候,和他所在父组件setState的时候才会触发数据刷新。

解决方案

我们可以用StateFulWidget包裹FutureBuilder,想要刷新FutureBuilder的数据,只需要刷新这个StateFulWidget就可以了,这样就不会影响到widgetTree中的其他组件。

import 'package:flutter/material.dart';

class RefreshableFutureBuilder<T> extends StatefulWidget {
  RefreshableFutureBuilder(
      {Key key,
        this.future,
        this.initialData,
        this.builder})
      : super(key: key);

  final Future<T> Function() future;
  final T initialData;
  final AsyncWidgetBuilder<T> builder;

  @override
  State<StatefulWidget> createState() => _RefreshableFutureBuilderState<T>();
}

class _RefreshableFutureBuilderState<T>
    extends State<RefreshableFutureBuilder> {

  @override
  Widget build(BuildContext context) => FutureBuilder(
            future: widget.future(),
            initialData: widget.initialData,
            builder: widget.builder);

}

调用

GlobalKey _key = GlobalKey();

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(),
        floatingActionButton: FloatingActionButton(
          child: Text('点我'),
          onPressed: () {
            _key.currentState.setState(() {

            });
          },
        ),
        body: Center(
          child: RefreshableFutureBuilder<List<ResponseData>>(
              key: _key,
              future: _getData,///注意这里传入的是方法,而不是方法返回值!!!
              initialData: [],
              builder: (BuildContext context, AsyncSnapshot snapshot) {
                if (snapshot.hasError) {
                  Scaffold.of(context)
                      .showSnackBar(SnackBar(content: snapshot.error));
                  return Container();
                }
                switch (snapshot.connectionState) {
                  case ConnectionState.none:
                    return Container();
                  case ConnectionState.active:
                    return Container();
                  case ConnectionState.waiting:
                    return CircularProgressIndicator();
                  default: // case ConnectionState.done:
                    return ListView.separated(
                      itemCount: snapshot.data.length,
                      separatorBuilder: (_, index) => Divider(),
                      itemBuilder: (_, index) => ListTile(
                        title: Text(snapshot.data[index].name),
                      ),
                    );
                }
              }),
        ),
      );

///访问接口方法
  Future<List<ResponseData>> _getData() async {
    var jsonData =
        await Dio().get('https://wanandroid.com/wxarticle/chapters/json');
    var result = ResponseEntity().fromJson(jsonData.data).data;
    return result;
  }
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部