I have a tabbed screen with two tabs. One of the tabs is loaded with a google maps view. On that map I need to place custom markers, which (place id and geo coordinates) I fetch from an API. The relevant API call function is inside a mixin which I returns this object from the function.
My approach is as follows.
- On tab view coming to screen, before the map view is shown to the user, I call this API function from the mixin.
- I await for the result in a future builder inside the tab screen(the one holds the google maps view tab and the other one).
- Soon after the function returns a response, I need to remove circular progress and show the two tab views.
- For the google maps tab view I pass the markers list (an object list) as a parameter so in that screens initstate it will load the custom markers in places on the map.
So far my future builder is not performing correctly. I will showcase what I tried so far.
Future Builder
SafeArea(
child: FutureBuilder(
future: dataFuture,
builder: (BuildContext ctx, AsyncSnapshot<dynamic> snapshot) {
// Checking if future is resolved or not
if (snapshot.connectionState == ConnectionState.done) {
// If we got an error
if (snapshot.hasError) {
// setState(() {});
return Center(
child: Text(
'${snapshot.error} occured',
style: TextStyle(fontSize: 18),
),
);
// if we got our data
} else if (snapshot.hasData) {
_markersSet = snapshot.data as MarkerList;
return Scaffold(
appBar: SearchBar(
isFilterEnabled: false,
),
body: _tabSection(),
floatingActionButton:
page == true ? listViewFAB() : mapViewFAB(),
);
} else {
return Center(
child: Text(
'${snapshot.error} occured',
style: TextStyle(fontSize: 18),
),
);
}
}
return Center(
child: CircularProgressIndicator(
color: CustomColors.green600,
strokeWidth: 6.0,
),
);
},
),
);
//the tab views
Widget _tabSection() {
return DefaultTabController(
// initialIndex: _selectedIndex,
length: 2,
child: TabBarView(
controller: _tabCtrl,
physics: NeverScrollableScrollPhysics(),
children: [
MainMapScreen(markersSet: _markersSet),
MapListScreen(markersSet: _markersSet),
],
),
);
}
//_markersSet is the list or markers to be drawn on top of google maps.
//and same list is passed to a list view of markers in the other tab view.
//I call the dataFuture in initState before super.initState()
dataFuture = await getVenueDetails();
Mixin class
mixin FetchMarkers {
final List<MarkerModel> eventList = [];
final List<MarkerModel> accessibleList = [];
late List<VenuesModel> vList = [];
//this is the list of markers I need to return above
late MarkerList? markersSet = new MarkerList();
Future<dynamic> getVenueDetails() async {
GetConnection().getConnect().then((value) async {
if (value) {
final res = await APIHandler.instance.getVenuesDetails(
endPoint: APIEndpoints.getVenues,
// id: id!,
);
if (res != null) {
if (res.code == 200) {
vList = res.data;
await loadEventList(vList);
await loadAccessList(vList);
//
markersSet!.acList = accessibleList;
markersSet!.evList = eventList;
//
log("get success venues ------------ ");
} else {
//status code not 200
log("get failed != 200 ------------ ");
}
} else {
//res is null
log("get failed no response ------------ ");
}
} else {
// 'No Network connectivity.\nPlease check the connection and try again',
log("get failed no network ------------ ");
}
return markersSet!;
});
}
Future<dynamic> loadEventList(List<VenuesModel> list) async {
//loading event markers
for (var i = 0; i < list.length; i++) {
if (list[i].hasEvents == true) {
var cats = list[i].categories;
List<int> cList = [];
for (var j in cats!) {
cList.add(j.categoryId!);
}
var lat = list[i].lat;
var lng = list[i].lng;
eventList.add(MarkerModel(
marker_id: i.toString(),
marker_title: list[i].name,
marker_pin: null,
categories: cList,
marker_place: list[i].venueId,
marker_loc: LatLng(lat!, lng!),
));
}
}
return eventList;
}
Future<dynamic> loadAccessList(List<VenuesModel> list) async {
//loading venue markers
for (var i = 0; i < list.length; i++) {
if (list[i].hasEvents == false) {
var cats = list[i].categories;
List<int> cList = [];
for (var j in cats!) {
cList.add(j.categoryId!);
}
var lat = list[i].lat;
var lng = list[i].lng;
accessibleList.add(MarkerModel(
marker_id: i.toString(),
marker_title: list[i].name,
marker_pin: null,
categories: cList,
marker_place: list[i].venueId,
marker_loc: LatLng(lat!, lng!),
));
}
}
return accessibleList;
}
}
After multiple debugs I didn't get a result from the future builder, and when debugging the future builders ,
if (snapshot.connectionState == ConnectionState.done) {...}
is invoked before the API call function finishes. What am I doing wrong here? Can I get some guidance to rectify the above issue and make it performed well with flutter. P.S. Im using dio package for API handling.