Как правильно получить API с помощью провайдера во Flutter - PullRequest
1 голос
/ 11 февраля 2020

В настоящее время я имею дело с проблемой, когда мне нужны данные из API для отображения их в моих виджетах. Я следую некоторому шаблону архитектуры провайдера, где вы устанавливаете состояние два раза:

1 - когда данные извлекаются

2 - когда данные уже извлекаются

Так что проблема Я сейчас имею дело, мой виджет выдает следующую ошибку:

setState() or markNeedsBuild() called during build.

Я знаю, что эта ошибка вызвана тем, что setState вызывается во время сборки, но .. как я могу получить мой API во время сборки, а затем показать его моим виджетам? Вот мой код:

NewsPage.dart

    class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  SideBarWidget _sidebar;

  @override
  void initState() {
    Provider.of<HomeViewModel>(context, listen: false)
        .fetchUltimaNoticia(context); --> ****Data to get fetched****
    _sidebar = const SideBarWidget();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('INICIO'),
        centerTitle: true,
        automaticallyImplyLeading: false,
        leading: Builder(
          builder: (context) => IconButton(
            icon: const Icon(Icons.menu),
            onPressed: () => Scaffold.of(context).openDrawer(),
          ),
        ),
      ),
      drawer: _sidebar,
      body: FormNoticiaContainer(),
    );
  }
}

FormContainer ()

Widget build(BuildContext context) {
    return _crearBodyNoticia(context);
  }

  Widget _crearBodyNoticia(context) {
    final homeVm = Provider.of<HomeViewModel>(context, listen: true);
    return homeVm.state == ViewState.Busy
        ? Center(child: CircularLoading())
        : Center(
            child: DataToShowWidget()

HomeViewModel.dart

    class HomeViewModel extends BaseModel {
  ////////
  //NOTICIAS
  ////////

  NoticiaDB _noticia;

  NoticiaDB get noticia => _noticia;

  set setNoticia(NoticiaDB noticia) {
    _noticia = noticia;
  }

  Future fetchUltimaNoticia(BuildContext context) async {
    setState(ViewState.Busy);

    var response = await noticiaProvider.obtenerNoticiaPublicada();

    setNoticia = response;

    setState(ViewState.Idle);
  }
}

BaseModel

 ViewState _state = ViewState.Idle;

  ViewState get state => _state;

  void setState(ViewState viewState) {
    _state = viewState;
    notifyListeners();
  }

1 Ответ

2 голосов
/ 11 февраля 2020

Вы можете использовать WidgetsBinding.instance.addPostFrameCallback
Для получения подробной информации, вы можете ссылаться на https://www.didierboelens.com/faq/week2/

фрагмент кода

@override
void initState(){
  super.initState();
  WidgetsBinding.instance.addPostFrameCallback((_){
    Provider.of<HomeViewModel>(context, listen: false)
    .fetchUltimaNoticia(context);  

  });
}
...