0

我有一个动态接受未来列表和回调的页面,以获取未来列表以接收数据并能够在刷新时刷新它。简化版本如下所示:

class ListSearchPage<T> extends StatefulWidget {

  final Future<List<T>> itemsFuture;
  final ValueGetter<Future<List<T>>> getItemsFuture;

  const ListSearchPage({Key key, this.getItemsFuture, this.itemsFuture})
      : super(key: key);

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


class _ListSearchPageState<T> extends State<ListSearchPage> {
  Future<List<T>> itemsFuture;
  TextEditingController _controller;

  @override
  void initState() {
    itemsFuture = widget.itemsFuture;
    _controller = TextEditingController();
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
              future:
                  itemsFuture != null ? itemsFuture : widget.getItemsFuture(),
              builder: (context, snapshot) {

                   return RefreshIndicator(
                     onRefresh: () async {
                        setState(() {
                          itemsFuture = null;
                          _controller.text = '';
                        });
                      },
                     child: ...
                   );
                });
    }
}

所以第一次,页面加载时已经加载了未来。当用户刷新时,我将未来标记为 null,以便调用回调并且可以重新获取数据。

我现在正在尝试在flutter_hooks整个应用程序中实现,并且我已将此小部件重构为如下所示(简化版本):


class ListSearchPage<T> extends HookWidget {
  
  final Future<List<T>> itemsFuture;
  final ValueGetter<Future<List<T>>> getItemsFuture;

  const ListSearchPage({Key key, this.getItemsFuture, this.itemsFuture})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    final itemsFutureNotifier = useState(this.itemsFuture);
    final TextEditingController _controller = useTextEditingController();
    return FutureBuilder(
              future:
              itemsFutureNotifier.value != null ? itemsFutureNotifier.value : getItemsFuture(),
              builder: (context, snapshot) {
                   return RefreshIndicator(
                     onRefresh: () async {
                        itemsFutureNotifier.value = null;
                        _controller.text = '';
                      },
                     child: ...
                   );
                });
    }

}

这第一次有效,但是之后该值继续分配给 null,因此值通知程序不会收到有关更改的通知。在这种情况下,如何像以前一样强制重建小部件?作为奖励,您是否看到了更好的解决方案?

提前致谢。

更新

这是itemsFuture

final future = useMemoized(() => repository.fetchData());

这是getItemsFuture

() => repository.fetchData()

它背后的想法是在打开搜索页面之前获取数据。在我的用例中有效。

我找到了解决问题的方法,但我不会将其发布为答案,因为我不相信它是干净的,我宁愿看看是否有人找到了正确的方法。

当前解决方案

@override
  Widget build(BuildContext context) {
    // feels like a dirty solution for rebuilding on refresh
    final counterNotifier = useState(0);
    final itemsFutureNotifier = useState(this.itemsFuture);
    final TextEditingController _controller = useTextEditingController();

 return ValueListenableBuilder(
            valueListenable: counterNotifier,
            builder: (context, value, child) {
return FutureBuilder(
              future:
              itemsFutureNotifier.value != null ? itemsFutureNotifier.value : getItemsFuture(),
              builder: (context, snapshot) {
                   return RefreshIndicator(
                     onRefresh: () async {
                        counterNotifier.value++;
                        itemsFutureNotifier.value = null;
                        _controller.text = '';
                      },
                     child: ...
                   );
                });
});

如您所见,我现在有一个计数器通知器,它将实际重建ValueListenableBuilderFutureBuilder获取数据

4

1 回答 1

1

我认为itemsFuture没有必要设置为 null (因为它可以是useState中的初始语句)。

@override
Widget build(BuildContext context) {
  final fetchData = useState(itemsFuture ?? getItemsFuture());

  return Scaffold(
    body: FutureBuilder(
      future: fetchData.value,
      builder: (context, snapshot) {
        return RefreshIndicator(
          onRefresh: () async {
            fetchData.value = getItemsFuture();
          },
          child: ...
        );
      },
    ),
  );
}
于 2020-12-25T05:54:08.880 回答