I'm currently dealing with a problem where I need some data from an API to show it into my widgets. I've following some Provider architecture pattern, where you setState two times:
1- When data is being fetched
2- When data is already fetched
So the problem I'm currently dealing is, my widget throws the following error:
setState() or markNeedsBuild() called during build.
I know this error is because setState is called during build, but.. how can I fetch my api during build, and then show it to my widgets? Here is my code:
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();
}
This article shows you a couple of different approaches to fetch data from APIs in Flutter. The first approach is using the HttpClient class and the second one is to use the http plugin from pub.dev.
If you are starting a project from scratch, you can create a new flutter project by using IDE or command. If you already have a flutter project skip this step. To add the http package, open your pubspec.yaml file and add the http package under the dependencies section. You can get the latest version of http package on pub.dev/packages/http.
Handling network requests and integrating APIs is one of the problems faced by Flutter beginners. Even I have faced these problems while developing Flutter applications. Converting JSON to dart objects, making a network call, state management, are a few things we have to consider while integrating APIs in a Flutter app.
Flutter calls the build () method often when it wants to change anything in the UI. If you leave the fetch call in your build () method, It will flood the API with unnecessary calls and slow down your app. So, you need to hit the API only when needed.
You can use WidgetsBinding.instance.addPostFrameCallback
For detail, you can reference https://www.didierboelens.com/faq/week2/
code snippet
@override
void initState(){
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_){
Provider.of<HomeViewModel>(context, listen: false)
.fetchUltimaNoticia(context);
});
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With