Item builder not getting triggered in futurbuilder Flutter - flutter

Scaffold(body: FutureBuilder(
future: fetchTracks(),
builder: (BuildContext context, AsyncSnapshot snapshot){
if(snapshot.hasData)
{
ListView.builder(
scrollDirection: Axis.vertical,
itemExtent: 130.0,
physics: AlwaysScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: trackes.length,
itemBuilder: (BuildContext context, int index) {
print("test");
return makeCard(snapshot.data[index]);
},
).build(context);
}
else
{
return Center(child: new CircularProgressIndicator());
}
} ));
When i call this Scaffold Future build will call my future function fetchTracks() and get the data in snapshot but it is not entering into itemBuilder function. So futurebuilder return NULL.
Please help me to solve .and Thank you in advance

You're missing a return before ListView.builder. If you don't return it, it won't build it.

FutureBuilder has different snapshot connectionstates which you must handle. Data on the stream is not available until ConnectionState equals done and hasData equals true.
_loadData(context)
{
showModalBottomSheet(
context: context,
builder: (BuildContext bc){
return FutureBuilder(
future: fetchTracks(),
builder: (BuildContext context, AsyncSnapshot<List<MyClass>> snapshot){
if (snapshot.connectionState!=ConnectionState.done)
{
return PleaseWaitWidget();
}
else if(snapshot.hasError)
{
DialogCaller.showErrorDialog(context,"future builder has an error").then((value){});
}
else if (snapshot.connectionState==ConnectionState.done)
{
if(snapshot.hasData){
List<Widget> list = snapshot.data.map((MyClass myClass){
return Card(
child:Wrap(children:<Widget>[
Row(children: [Text(myClass.field1)],),
]));}).toList();
return list;
}
}
});
});
}

Related

Flutter how to refresh appBar Title after FutureBuilder

Is it possible to refresh appBar title after widget FutureBuilder ?
I'd like to set title after FutureBuilder is done
class _SimpleBarChart extends State<SimpleBarChartPage> {
String _appBarTitle = '';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text(_appBarTitle)),
body: Center(child: futureCAGraph()));
}
futureCAGraph() {
return FutureBuilder(
future: BddAMKGraphCA().getDataGraphCA(_caAnnee),
builder: (context, AsyncSnapshot<List<dynamic>> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, int currentIndex) {
return affGraphCA(context);
});
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
//return a circular progress indicator.
return new CircularProgressIndicator();
});
}
You Just Have to update Text(_appBarTitle) with Text(snapshot.data[Index].title)
you can easily update it with setstate() after you get data from future. just assign _appBarTitle in setstate() as shown below,
setState(() {
_appBarTitle=//assign your snapshot data
});
It's not a good practice to call setState during the build method. Instead you can move Scaffold inside the builder like this:
Widget build(BuildContext context) {
return FutureBuilder(
future: BddAMKGraphCA().getDataGraphCA(_caAnnee),
builder: (context, AsyncSnapshot<List<dynamic>> snapshot)
=> Scaffold(
appBar: AppBar(title: Text(_appBarTitle)),
body: Center(child: (snapshot.hasData)
? ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, int currentIndex) {
return affGraphCA(context);
})
: (snapshot.hasError)
? Text('${snapshot.error}')
: //return a circular progress indicator.
CircularProgressIndicator(),
),
)
);
}
Sorry, after testing appBar's title don't print anything
Widget build(BuildContext context) {
return FutureBuilder(
future: BddAMKGraphCA().getDataGraphCA(_caAnnee),
builder: (context, AsyncSnapshot<List<dynamic>> snapshot)
=> Scaffold(
appBar: AppBar(title: Text(_appBarTitle)),
body: Center(child: (snapshot.hasData)
? ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, int currentIndex) {
**print('appBar something');**
return affGraphCA(context);
})
: (snapshot.hasError)
? Text('${snapshot.error}')
: //return a circular progress indicator.
CircularProgressIndicator(),
),
)
);
}

I have a problem about using FutureBuilder in Flutter

I have a problem about using FutureBuilder in Flutter.
With FutureBuilder, the page is continuously rebuilt.
I've omitted the detailed code to write the question. If you want to see additional code, please leave a comment.
To stop this, What can I do?
Future<bool> initLikes() async {
var list = await ApiProvider().post('/RoomSalesInfo/Select/Like', jsonEncode(
{
"userID" : GlobalProfile.loggedInUser.userID,
}
));
return true;
} else {
return false;
}
}
//This is the Code that I use in Widget build
FutureBuilder(
future: initLikes(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
//해당 부분은 data를 아직 받아 오지 못했을때 실행되는 부분을 의미한다.
if (snapshot.hasData == false) {
return SizedBox();
}
//error가 발생하게 될 경우 반환하게 되는 부분
// 데이터를 정상적으로 받아오게 되면 다음 부분을 실행하게 되는 것이다.
else {
return Expanded(
child: ListView.builder(
physics: ClampingScrollPhysics(),
shrinkWrap: true,
scrollDirection: Axis.vertical,
controller: _scrollController,
itemCount: GlobalProfile.listForMe.length +1,
itemBuilder: (BuildContext context, int index) {
if(index == GlobalProfile.listForMe.length){
return CupertinoActivityIndicator();
}
else
return Column();
}
),
);
}
})
future: initLikes(),
Don't recomputing this. The new invocation will overwrite the old one. Instead use an initState() to compute it just once into a variable that you reference from "future:..".

Streambuilder not updating when firestore changes

I have an animated list, the build function is included in a stack from the body of the app.
Whenever somethings updates in the database, the streambuilder doesn't rebuild..
items is set in the init by the function:
Stream<List<Task>> getTasks(){
try {
Firestore.instance
.collection("lists")
.document(tasklist.postID)
.collection("tasks")
.snapshots();
}
on Exception {
error();
}
return ref.snapshots().map((list) =>
list.documents.map((doc) => Task.fromFireStore(doc)).toList());
}
Widget _buildTasksList() {
return new Expanded(
child: new StreamBuilder(
stream: items,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return new Text("Loading");
}
return new AnimatedList(
initialItemCount: tasks.length,
key: _listKey,
itemBuilder: (context, index, animation) {
print(index);
return new TaskRow(
task: listModel[index],
animation: animation,
listModel: listModel,
tasklist: tasklist,
onChange: () => _onChange(listModel[index]),
);
},
);
},
)
);
}
had the wrong initialItemCount, should have been items.length

Update ListView.builder itemCount when firestore document is added

I have a flutter app where a list is generated with ListView.Builder, and where the itemCount is the number of documents in a firestore collection. This works fine until a new document is added. When that happens I get the error (17 and 18 are just examples).
Invalid value: Not in range 0..17, inclusive: 18
I assume I would need to update the state when a new document is created, but I have no idea how i can call setState when that happens
Here is the relevant part of the code:
child: StreamBuilder(
stream: Firestore.instance.collection('contact').orderBy(sortby, descending: decending).snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) return Container();
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
_personer(context, snapshot.data.documents[index], index),
);
},
),
use setState?
StreamBuilder(builder: (context, snapshot) {
return snapshot.hasData == null ? Container() : _getListView(snapshot);
} , )
_getListView(snapshot) {
setState(() {
return ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) =>
_personer(context, snapshot.data.documents[index], index),
);
});
}
StreamBuilder use QuerySnapshot so list data can change
example code :
StreamBuilder<QuerySnapshot>(
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError)
return new Text('Error: ${snapshot.error}');
switch (snapshot.connectionState) {
case ConnectionState.waiting: return new Text('Loading...');
default:
return new ListView(
children: snapshot.data.documents.map((DocumentSnapshot document) {
return ;
}).toList(),
);
}
},
)

(Flutter) ListView.builder using FutureBuilder not working

I am trying to display items in a ListView using ListView.builder inside a FutureBuilder. My future function for FutureBuilder looks like this:
_fetchListItems() async {
wait() async {
number = await db.getNumber(userId); }
await wait();
List rawFavouriteList = await db.getList(number);
setState((){
rawFavouriteList.forEach((item){
_faouriteList.add(Model.map(item));
}});
return _faouriteList;
}
My FutureBuilder looks like this:
FutureBuilder(
future: _fetchListItems(),
builder:(context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
} else {Container( child: ListView.builder(
itemCount: _faouriteList.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Text(
'${_faouriteList[index].title}');
}));}})
he following assertion was thrown building FutureBuilder(dirty, state:
I/flutter (24728): _FutureBuilderState#f12a3):
I/flutter (24728): A build function returned null.
I/flutter (24728): The offending widget is: FutureBuilder
I/flutter (24728): Build functions must never return null
Another exception was thrown: A build function returned null.
Note:
I tried to call _fetchListItems() from initState and not use FutureBuilder and that didn't work for me as well.
Here is a link to that case: (Flutter/Dart) Two async methods in initState not working
Please let me know if I should use FutureBuilder or initState to wait for List to load it's data. And how to make it work since none of the methods seem to work for me :(
Your fetch _fetchListItems method is not the problem as far as I can tell.
Your error message is very clear, " a build function returned null". In this case, the method that returns null is the anonymous function passed as the builder argument to the FutureBuilder. You're just missing the return keyword inside the else case because you're just creating the instance of Container but not returning it.
Something like this:
FutureBuilder(
future: _fetchListItems(),
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}');
}
)
);
}
}
)
I don't know if there are any other problems with your code but this should solve the particular error message you are asking about.
It is not necessary to use setState for your case, try this:
Fetch async function
_fetchListItems() async {
number = await db.getNumber(userId);
List rawFavouriteList = await db.getList(number);
List _faouriteList = rawFavouriteList.map((item)=>Model.map(item)).toList();
return _faouriteList;
}
FutureBuilder
FutureBuilder(
future: _fetchListItems(),
builder: (context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
} else {
Container(
child: ListView.builder(
itemCount: snapshot.data.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
return Text('${snapshot.data[index].title}');
}));
}
});