The below code does not display any data when the bottomsheet loads. Once the bottomsheet is loaded if I do a save operation on the code editor it loads the data. What am I missing here?
I have a bottomsheet widget which is invoked using a button.
_showBottomSheet() {
showModalBottomSheet(
context: context,
builder: (context) {
return const Contacts();
},
);
}
The above code loads up the Contacts widget that has a Listview.builder in it which is below.
class Contacts extends StatefulWidget {
const Contacts({Key? key}) : super(key: key);
@override
_ContactsState createState() => _ContactsState();
}
class _ContactsState extends State<Contacts> {
List<PhoneBookContact> phoneBookContacts1 = [];
List<PhoneBookContact> phoneBookContacts2 = [];
@override
void initState() {
loadContacts();
super.initState();
}
Future loadContacts() async {
///somecode to gather data for the listview builder
///populates the phoneBookContacts1 & phoneBookContacts2 lists
}
@override
Widget build(BuildContext context) {
return Column(children: [
const Text('Contacts Set 1'),
displayPhoneBookContacts(phoneBookContacts1),
const Text('Contacts Set 2'),
displayPhoneBookContacts(phoneBookContacts2),
]);
}
Widget displayPhoneBookContacts(phoneBookContacts) {
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: phoneBookContacts.length,
itemBuilder: (BuildContext context, int index) {
return Card(
margin: const EdgeInsets.all(10),
child: ListTile(
contentPadding: const EdgeInsets.all(10),
title: Column(
children: [
Text(phoneBookContacts[index].phoneBookContact.toString()),
const SizedBox(
height: 20,
),
ListView.separated(
physics: const ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: phoneBookContacts[index].contactNumbers!.length,
separatorBuilder: (BuildContext context, int index) =>
const Divider(),
itemBuilder: (BuildContext context, int phoneIndex) {
return InkWell(
onTap: () {},
child: Row(
children: [
Text(phoneBookContacts[index]
.contactNumbers![phoneIndex]
.phone),
],
),
);
},
),
],
),
),
);
},
),
);
}
}
CodePudding user response:
I don't prefer using FutureBuilder
inside StatefulWidget
., it will recall the API(future
) on every setState
. As for comment it is missing setState
after initializing the data.
@override
void initState() {
super.initState();
loadContacts();
}
Future loadContacts() async {
///somecode to gather data for the listview builder
///populates the phoneBookContacts1 & phoneBookContacts2
setState(() {});// make sure to call setState
}
CodePudding user response:
Because function initState()
don't await your loadContacts()
, data loaded after function build()
.
You need use FutureBuilder class to rebuild ListView widget after load data
Example:
FutureBuilder(
future: loadContacts(),
builder:(context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
} else {
return Container(
child: ListView.builder(
itemCount: _faouriteList.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Text('${_faouriteList[index].title}');
}
)
);
}
}
)