在正文中重用Future调用的推荐方法/最佳实践是什么



我是flutter的新手,我遇到了一种需要重用异步调用数据的情况,在研究了一点之后,我发现了我正在使用的漂亮的FutureBuilder Widget,它工作得很好,但我有这样的情况,我需要在两个不同的小部件中来自未来调用的数据,比如下面的代码片段,这会导致异步调用执行两次,我希望避免它

如何避免这两个电话?在这种情况下,建议采用什么方法?我找不到适合这种情况的推荐信。

body: Column(
children: [
Container(
height: 200,
child: FutureBuilder(
future: weight.findAll(),
builder: (context, snapshot) {
if(!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
} else {
this._seriesList = _plotWeightSeries(snapshot.data);
return _lineChart();
}
},
),
),
Expanded(
child: FutureBuilder(
future: weight.findAll(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
} else {
return _getSlidableListView(snapshot.data);
}
},
),
),
],
),

下面是一个使用Flutter Hooks和Riverpod的示例。

我定义了一个FutureProvider来从服务器获取权重:

final weightsProvider = FutureProvider((ref) => findAllWeights());
Future<List<double>> findAllWeights() async {
print('FETCHING DATA'); // This gets run only once
final random = Random();
await Future.delayed(Duration(seconds: 2));
return List.generate(20, (index) => 50 + 20 * random.nextDouble());
}

然后,我使用WidgetOne中的结果来计算SUM,并使用WidgetTwo来计算AVERAGE。正如您将看到的,FETCHING DATA只发生一次。

完整源代码

import 'dart:math' show Random;
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/all.dart';
void main() {
runApp(
ProviderScope(
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
),
);
}
final weightsProvider = FutureProvider((ref) => findAllWeights());
Future<List<double>> findAllWeights() async {
print('FETCHING DATA'); // This gets run only once
final random = Random();
await Future.delayed(Duration(seconds: 2));
return List.generate(20, (index) => 50 + 20 * random.nextDouble());
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
WidgetOne(),
WidgetTwo(),
],
),
);
}
}
class WidgetOne extends HookWidget {
@override
Widget build(BuildContext context) {
final weights = useProvider(weightsProvider);
return Card(
child: Column(
children: [
Text('SUM of the weights'),
weights.when(
data: (data) => Text(data.reduce((a, b) => a + b).toString()),
loading: () => CircularProgressIndicator(),
error: (_, __) => Text('Something bad happended'),
),
],
),
);
}
}
class WidgetTwo extends HookWidget {
@override
Widget build(BuildContext context) {
final weights = useProvider(weightsProvider);
return Card(
child: Column(
children: [
Text('AVERAGE of the weights'),
weights.when(
data: (data) =>
Text((data.reduce((a, b) => a + b) / data.length).toString()),
loading: () => CircularProgressIndicator(),
error: (_, __) => Text('Something bad happended'),
),
],
),
);
}
}

我在这个例子中使用了Riverpod,但还有其他州管理,请查看这里的州管理方法列表。

Riverpod 1.0的更新

import 'dart:math' show Random;
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
void main() {
runApp(
const ProviderScope(
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
home: HomePage(),
),
),
);
}
final weightsProvider = FutureProvider((ref) => findAllWeights());
Future<List<double>> findAllWeights() async {
print('FETCHING DATA'); // This gets run only once
final random = Random();
await Future.delayed(const Duration(seconds: 2));
return List.generate(20, (index) => 50 + 20 * random.nextDouble());
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: const [
WidgetOne(),
WidgetTwo(),
],
),
);
}
}
class WidgetOne extends HookConsumerWidget {
const WidgetOne({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final weights = ref.watch(weightsProvider);
return Card(
child: Column(
children: [
const Text('SUM of the weights'),
weights.when(
data: (data) => Text(data.reduce((a, b) => a + b).toString()),
loading: () => const CircularProgressIndicator(),
error: (_, __) => const Text('Something bad happended'),
),
],
),
);
}
}
class WidgetTwo extends HookConsumerWidget {
const WidgetTwo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final weights = ref.watch(weightsProvider);
return Card(
child: Column(
children: [
const Text('AVERAGE of the weights'),
weights.when(
data: (data) =>
Text((data.reduce((a, b) => a + b) / data.length).toString()),
loading: () => const CircularProgressIndicator(),
error: (_, __) => const Text('Something bad happended'),
),
],
),
);
}
}

最新更新