Flutter: как получить данные из api только один раз при использовании FutureBuilder?
Как я могу получить данные только один раз при использовании FutureBuilder, чтобы во время выборки отображался индикатор загрузки?
Проблема в том, что каждый раз, когда пользователь открывает экран, он повторно выбирает данные, даже если я установил будущее в initState().
Я хочу получить данные только при первом открытии экрана пользователем, тогда я буду использовать сохраненные полученные данные.
мне просто использовать виджет с отслеживанием состояния с переменной загрузки и установить его в 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(),
),
);
}
}
4 ответа
Если вы хотите получить данные только один раз, даже если виджет перестраивается, вам придется создать для этого модель. Вот как его можно сделать:
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 как Provider. В вашем FutureBuilder:
@override
Widget build(context) {
final myModel=Provider.of<MyModel>(context)
return FutureBuilder<String>(
future: myModel.fetchData(),
builder: (context, snapshot) {
// ...
}
);
}
Простой подход - представить StatefulWidget, в котором мы храним наше будущее в переменной. Теперь каждая перестройка будет ссылаться на один и тот же экземпляр 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...'),
),
);
}
}
Вы можете реализовать поставщика и передавать данные его дочернему элементу. Обратитесь к этому примеру, чтобы получить данные один раз и использовать их во всем дочернем элементе.
Как предложил Аашутош Пудель, вы можете использовать внешний объект для поддержания своего состояния,
ДЛЯ ДРУГИХ, ПРИХОДЯЩИХ ЗДЕСЬ!
Для управления состоянием больших приложений управление виджетами с отслеживанием состояния становится немного болезненным. Следовательно, вы должны использовать внешний объект состояния, который должен быть вашим единственным источником истины.
Управление состоянием во флаттере осуществляется следующими библиотеками | услуги :
я. Провайдер: Ну, лично я с этим немного поигрался, даже что-то с этим сделал. Я мог бы предложить это для начинающих.
II. GetX: это единственная библиотека, которая может делать все, она хороша и рекомендуется для новичков || нуб.
III. Redux: для тех, кто приходит из мира реагирования и углов, чтобы порхать, это очень удобная библиотека. Я лично обожаю эту библиотеку, плюс когда к ней добавляешь дополнительные плагины, ты просто супермен
IV. Блок: лучше всего подходит для данных, которые находятся в потоках. другими словами, лучше всего подходит для реактивного программирования....
В любом случае, это было много, учитывая ваш вопрос. Надеюсь, я помог