我有一个页面,它动态地接受未来列表和回调,以获取未来列表来接收数据,并能够在刷新时对其进行刷新。简化版本如下:
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
没有必要设置为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: ...
);
},
),
);
}