【发布时间】:2020-12-23 15:19:44
【问题描述】:
我有一个页面动态接受未来列表和回调以获取未来列表以接收数据并能够在刷新时刷新它。简化版如下所示:
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: ...
);
});
}
}
所以第一次,页面加载时已经加载了未来。当用户刷新时,我将 future 标记为 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: ...
);
});
});
如您所见,我现在有一个计数器通知器,它将实际重建 ValueListenableBuilder 并使 FutureBuilder 获取数据
【问题讨论】:
-
只是好奇。
itemsFuture和getItemsFuture可以是同一个函数,使用不同的参数,如 bool forceRefetch。其次,itemsFuture是 null onCreate 还是只使用null来检测页面是否需要刷新? -
itemsFuture could onCreate 为空,
itemsFuture是getItemsFuture的结果 -
itemsFuture有必要成为未来数据吗?你能展示一些描述itemsFuture和getItemsFuture之间关系的代码吗?如果没有必要,我认为这应该比将 Future 数据设置为 null 更好。 -
我已经编辑了问题以添加解释
标签: flutter flutter-hooks