使用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: ...
);
});
}
}

所以第一次,页面加载时已经加载了未来。当用户刷新时,我将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: ...
);
},
),
);
}

相关内容

  • 没有找到相关文章

最新更新