如何解决在 Flutter 中使用 Hook Widget 强制构建小部件树
我有一个页面,它动态地接受未来列表和回调以获取未来列表以接收数据并能够在刷新时刷新它。简化版本如下所示:
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.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(),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,value,child) {
return FutureBuilder(
future:
itemsFutureNotifier.value != null ? itemsFutureNotifier.value : getItemsFuture(),snapshot) {
return Refreshindicator(
onRefresh: () async {
counterNotifier.value++;
itemsFutureNotifier.value = null;
_controller.text = '';
},child: ...
);
});
});
如您所见,我现在有一个计数器通知程序,它将实际重建 ValueListenableBuilder
并使 FutureBuilder
获取数据
解决方法
我认为 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: ...
);
},),);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。