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(),
),
)
);
}
Related
class _Requests_TabState extends State<Requests_Tab> {
Future<Product> productdata = getPostById();
#override
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
body: Center(
child: FutureBuilder(
future: productdata,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data.title);
} else if (snapshot.hasError) {
return Text("${snapshot.error}");
}
CircularProgressIndicator();
},
),
),
return Text(snapshot.data[title].toString());
I want to compound firestore datas. Which widget is useful for multiple data?
For instance, i have user datas and user post's datas. I want to show them in the same Card Widget, but their snapshots are different. How can i compound them ?
I write just like this, but it shows just 1 snapshot, i want to both futurebuilder and streambuilder snapshots:
note: i can't use user datas, in below it has final dataUser = snapshotUser.data;
but i can't use it, it gives an error
class HomePageBodyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) => StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collectionGroup('Posts').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
return ListView(
children: snapshot.data.docs.map((DocumentSnapshot docPost) {
return FutureBuilder(
future: FirebaseFirestore.instance
.collection('Users')
.doc(docPost.reference.parent.parent.id)
.get(),
builder: (context, snapshotUser) {
if (!snapshotUser.hasData) {
return Center(child: CircularProgressIndicator());
}
return homePageCard(context, dataPost: docPost, dataUser: snapshotUser.data);
},
);
}).toList());
});
}
i solved it, like this:
class HomePageBodyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) => StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collectionGroup('Posts').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasError) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
}
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
return ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
final dataPost = snapshot.data.docs[index];
return FutureBuilder(
future: FirebaseFirestore.instance
.collection('Users')
.doc(dataPost.reference.parent.parent.id)
.get(),
builder: (context, snapshotUser) {
final dataUser = snapshotUser.data;
if (!snapshotUser.hasData) {
return Center(child: CircularProgressIndicator());
}
return homePageCard(context,
dataPost: dataPost, dataUser: dataUser);
},
);
});
});
}
I have a json file saved in my assets folder, all i wanted to do is just display the json file in my Listview.Builder which I'm successfully getting it displayed, but the problem here is before the App is getting initialized I'm getting the following error in the console not on the mobile screen.
The following NoSuchMethodError was thrown building FutureBuilder<String>(dirty, state:
I/flutter (11766): _FutureBuilderState<String>#ef73b):
I/flutter (11766): The getter 'length' was called on null.
I/flutter (11766): Receiver: null
I/flutter (11766): Tried calling: length
And this is my code
class _OfficeScreenState extends State<OfficeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: FutureBuilder(
builder: (context, snapshot){
var showData = json.decode(snapshot.data.toString());
return ListView.builder(
itemBuilder: (BuildContext context, int index){
return ListTile(
title: Text(showData[index]['OfficeName']),
subtitle: Text(showData[index]['Pincode']),
);
},
itemCount: showData.length,
);
}, future: DefaultAssetBundle.of(context).loadString('assets/json/office.json'),
),
),
);
}
}
You should add hasData check before rendering the list
if(snapshot.hasData) {
// build the list
}
...
// build the wait message
You need to add the Future element before Builder. This can point to a Future method, which supply the data
Add an if condition like if(snapshot.data!=null), then provide the code, else return a CircularProgressIndicator widget
Check first snapshot.hasData, if not Show some loading widget
class _OfficeScreenState extends State<OfficeScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: FutureBuilder(
builder: (context, snapshot) {
var showData = json.decode(snapshot.data.toString());
if (snapshot.hasData) {
return ListView.builder(
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(showData[index]['OfficeName']),
subtitle: Text(showData[index]['Pincode']),
);
},
itemCount: showData.length,
);
} else
return Center(
child: CircularProgressIndicator(),
);
},
future: DefaultAssetBundle.of(context)
.loadString('assets/json/office.json'),
),
),
);
}
}
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;
}
}
});
});
}
I am trying to show Circular Progress Indicator while my data in Future Builder loads, I tried two methods to add it however both of them didn't work. How can I achieve the desired result?
My code
class _MyHomePageState extends State<MyHomePage>{
#override MyHomePage get widget => super.widget;
#override
Widget build(BuildContext context){
//To show the ListView inside the Future Builder
Widget createTasksListView(BuildContext context, AsyncSnapshot snapshot) {
var values = snapshot.data;
return ListView.builder(
itemCount: values == null ? 0 : values.length,
itemBuilder: (BuildContext context, int index) {
return values.isNotEmpty ? Ink(
.....
) : new CircularProgressIndicator(); //TRIED TO ADD CIRCULAR INDICATOR HERE
},
);
}
//Future Builder widget
Column cardsView = Column(
children: <Widget>[...
Expanded(
child: FutureBuilder(
future: //API CALL,
initialData: [],
builder: (context, snapshot) {
if (!snapshot.hasData) return Center(child: CircularProgressIndicator()); //CIRCULAR INDICATOR
return createTasksListView(context, snapshot);
}),
),
],
);
return Scaffold(
...);
}
}
Try with:
FutureBuilder(
future: //API CALL,
initialData: [],
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator()); //CIRCULAR INDICATOR
else
return createTasksListView(context, snapshot);
}),
),
When the value of the future is an empty list, which is your initialData, you are rendering a ListView with 0 items, so you cannot render a CircularProgressIndicator in its itemBuilder.