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. Блок: лучше всего подходит для данных, которые находятся в потоках. другими словами, лучше всего подходит для реактивного программирования....

В любом случае, это было много, учитывая ваш вопрос. Надеюсь, я помог

Другие вопросы по тегам