Flutter:如何在使用 FutureBuilder 时仅从 api 中获取一次数据?
Flutter: How to fetch data from api only once while using FutureBuilder?
如何在使用 FutureBuilder 显示加载指示器时仅获取一次数据?
问题是每次用户打开屏幕都会重新获取数据,即使我在 initState() 中设置了 future。
我只想在用户第一次打开屏幕时获取数据,然后我将使用保存的获取数据。
我应该只使用带有加载变量的有状态小部件并将其设置在 setState() 中吗?
我正在使用提供程序包
Future<void> fetchData() async {
try {
final response =
await http.get(url, headers: {'Authorization': 'Bearer $_token'});......
和我的屏幕小部件:
class _MyScreenState extends State<MyScreen> {
Future<void> fetchData;
@override
void initState() {
fetchData =
Provider.of<Data>(context, listen: false).fetchData();
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: fetchData,
builder: (ctx, snapshot) =>
snapshot.connectionState == ConnectionState.done
? Consumer<Data>(
builder: (context, data, child) => Text(data.fetchedData)): Center(
child: CircularProgressIndicator(),
),
);
}
}
一个简单的方法是引入一个 StatefulWidget,我们将 Future 存储在一个变量中。现在每次重建都会引用同一个 Future 实例:
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
Future<String> _future;
@override
void initState() {
_future = callAsyncFetch();
super.initState();
}
@override
Widget build(context) {
return FutureBuilder<String>(
future: _future,
builder: (context, snapshot) {
// ...
}
);
}
}
或者您可以简单地使用 FutureProvider 而不是上面的 StatefulWidget:
class MyWidget extends StatelessWidget {
// Future<String> callAsyncFetch() => Future.delayed(Duration(seconds: 2), () => "hi");
@override
Widget build(BuildContext context) {
// print('building widget');
return FutureProvider<String>(
create: (_) {
// print('calling future');
return callAsyncFetch();
},
child: Consumer<String>(
builder: (_, value, __) => Text(value ?? 'Loading...'),
),
);
}
}
如果即使小部件重建也只想获取一次数据,则必须为此创建一个模型。制作方法如下:
class MyModel{
String value;
Future<String> fetchData() async {
if(value==null){
try {
final response =
await http.get(url, headers: {'Authorization': 'Bearer $_token'});......
value=(YourReturnedString)
}
}
return value;
}
}
不要忘记将 MyModel 作为提供者。在您的 FutureBuilder 中:
@override
Widget build(context) {
final myModel=Provider.of<MyModel>(context)
return FutureBuilder<String>(
future: myModel.fetchData(),
builder: (context, snapshot) {
// ...
}
);
}
您可以实现提供程序并在其子项之间传递数据。
参考这个 example for fetching the data once and using it throughout its child.
正如 Aashutosh Poudel 所建议的,您可以使用外部对象来维护您的状态,
对于其他来到这里的人!
要管理大型应用程序的状态,有状态的小部件管理变得有点痛苦。因此,您必须使用一个外部状态对象,它应该是您唯一的真实来源。
flutter 中的状态管理由以下库完成 | 服务:
我。 Provider:好吧,我个人玩过一点,甚至用它做了一些事情。我可以向初学者推荐这个。
二。 GetX: 那个无所不能的库,不错,新手推荐||菜鸟.
三。 Redux:对于来自 React 和 angular 世界的任何人来说,这是一个非常方便的库。我个人很喜欢这个库,再加上当你给它额外的插件时,你就是超人
四。 Bloc:最适合流中的数据。换句话说,最适合反应式编程方法....
无论如何,鉴于您的问题,这已经很多了。希望我能帮到你
如何在使用 FutureBuilder 显示加载指示器时仅获取一次数据?
问题是每次用户打开屏幕都会重新获取数据,即使我在 initState() 中设置了 future。
我只想在用户第一次打开屏幕时获取数据,然后我将使用保存的获取数据。
我应该只使用带有加载变量的有状态小部件并将其设置在 setState() 中吗?
我正在使用提供程序包
Future<void> fetchData() async {
try {
final response =
await http.get(url, headers: {'Authorization': 'Bearer $_token'});......
和我的屏幕小部件:
class _MyScreenState extends State<MyScreen> {
Future<void> fetchData;
@override
void initState() {
fetchData =
Provider.of<Data>(context, listen: false).fetchData();
super.initState();
}
@override
Widget build(BuildContext context) {
return FutureBuilder(
future: fetchData,
builder: (ctx, snapshot) =>
snapshot.connectionState == ConnectionState.done
? Consumer<Data>(
builder: (context, data, child) => Text(data.fetchedData)): Center(
child: CircularProgressIndicator(),
),
);
}
}
一个简单的方法是引入一个 StatefulWidget,我们将 Future 存储在一个变量中。现在每次重建都会引用同一个 Future 实例:
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
Future<String> _future;
@override
void initState() {
_future = callAsyncFetch();
super.initState();
}
@override
Widget build(context) {
return FutureBuilder<String>(
future: _future,
builder: (context, snapshot) {
// ...
}
);
}
}
或者您可以简单地使用 FutureProvider 而不是上面的 StatefulWidget:
class MyWidget extends StatelessWidget {
// Future<String> callAsyncFetch() => Future.delayed(Duration(seconds: 2), () => "hi");
@override
Widget build(BuildContext context) {
// print('building widget');
return FutureProvider<String>(
create: (_) {
// print('calling future');
return callAsyncFetch();
},
child: Consumer<String>(
builder: (_, value, __) => Text(value ?? 'Loading...'),
),
);
}
}
如果即使小部件重建也只想获取一次数据,则必须为此创建一个模型。制作方法如下:
class MyModel{
String value;
Future<String> fetchData() async {
if(value==null){
try {
final response =
await http.get(url, headers: {'Authorization': 'Bearer $_token'});......
value=(YourReturnedString)
}
}
return value;
}
}
不要忘记将 MyModel 作为提供者。在您的 FutureBuilder 中:
@override
Widget build(context) {
final myModel=Provider.of<MyModel>(context)
return FutureBuilder<String>(
future: myModel.fetchData(),
builder: (context, snapshot) {
// ...
}
);
}
您可以实现提供程序并在其子项之间传递数据。 参考这个 example for fetching the data once and using it throughout its child.
正如 Aashutosh Poudel 所建议的,您可以使用外部对象来维护您的状态,
对于其他来到这里的人!
要管理大型应用程序的状态,有状态的小部件管理变得有点痛苦。因此,您必须使用一个外部状态对象,它应该是您唯一的真实来源。
flutter 中的状态管理由以下库完成 | 服务:
我。 Provider:好吧,我个人玩过一点,甚至用它做了一些事情。我可以向初学者推荐这个。
二。 GetX: 那个无所不能的库,不错,新手推荐||菜鸟.
三。 Redux:对于来自 React 和 angular 世界的任何人来说,这是一个非常方便的库。我个人很喜欢这个库,再加上当你给它额外的插件时,你就是超人
四。 Bloc:最适合流中的数据。换句话说,最适合反应式编程方法....
无论如何,鉴于您的问题,这已经很多了。希望我能帮到你