Future builder return value keeps blinking - flutter

I have a screen with a container that shows the current time and under that a list view that contains list tiles with different regions and their corresponding time. I have a Future function that gets the time of a location. The problem is the text field that I have wrapped with future builder keeps blinking. It goes from null to time and back and forth. I want it to keep rebuilding to update the time, but how I do remove the blinking problem. and when I wrap newTime in setState it returns null. Any help will be really appreciated
class _WorldClockState extends State<WorldClock> {
final WorldTimeController worldTimeController =
Get.put(WorldTimeController());
String formattedTime = DateFormat('h:mm').format(DateTime.now());
String hour = DateFormat('a').format(DateTime.now());
late Timer _timer;
var location;
var time;
#override
void initState() {
super.initState();
_timer =
Timer.periodic(const Duration(milliseconds: 500), (timer) => _update());
}
void _update() {
setState(() {
formattedTime = DateFormat('h:mm').format(DateTime.now());
hour = DateFormat('a').format(DateTime.now());
});
}
var newUrl;
var newResponse;
getTime(location) async {
newUrl = "http://worldtimeapi.org/api/timezone/$location";
newResponse = await get(Uri.parse(newUrl));
Map newData = jsonDecode(newResponse.body);
var time = newData['datetime'];
String dateTime = newData["utc_datetime"];
String offset = newData["utc_offset"];
DateTime now = DateTime.parse(dateTime);
now = now.add(Duration(
hours: int.parse(offset.substring(1, 3)),
minutes: int.parse(offset.substring(4))));
String newtime = DateFormat.jm().format(now);
return newtime;
}
#override
void dispose() {
_timer.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(formattedTime,
style: GoogleFonts.lato(
fontSize: 80.0,
color: Colors.blue,
fontStyle: FontStyle.normal,
letterSpacing: 5.0)),
Padding(
padding: const EdgeInsets.only(top: 40.0, left: 5.0),
child: Text(
hour,
style: GoogleFonts.lato(
color: Colors.blue,
fontSize: 30.0,
),
),
),
],
),
),
Container(
child: Text(
DateFormat('EE, MMM d').format(DateTime.now()),
style: GoogleFonts.lato(
color: Colors.white,
fontSize: 20.0,
letterSpacing: 2.0,
),
),
),
const Padding(
padding: EdgeInsets.only(top: 20.0, left: 30.0, right: 30.0),
child: Divider(
color: Colors.white,
height: 2.0,
),
),
Container(
height: 600.0,
width: 450.0,
child: Padding(
padding: const EdgeInsets.only(top: 20.0),
child: ListView.builder(
scrollDirection: Axis.vertical,
physics: const BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: worldTimeController.WorldTimeList.length,
itemBuilder: (BuildContext context, index) => Padding(
padding: const EdgeInsets.only(bottom: 18.0),
child: Slidable(
key: UniqueKey(),
startActionPane: ActionPane(
motion: ScrollMotion(),
dismissible: DismissiblePane(onDismissed: () {
worldTimeController.WorldTimeList.removeAt(index);
}),
children: const [],
),
child: ListTile(
leading: Text(
worldTimeController.WorldTimeList[index].location,
style: GoogleFonts.lato(
color: Colors.white70, fontSize: 25)),
trailing: FutureBuilder(
future: getTime(worldTimeController
.WorldTimeList[index].location),
builder: (context, AsyncSnapshot snapshot) {
return Text(
'${snapshot.data}',
style: GoogleFonts.lato(
color: Colors.white70, fontSize: 35.0),
);
}),
),
),
),
),
),
)
],
),
),

Replace your Future Func
FutureBuilder(
future: getTime(worldTimeController.WorldTimeList[index].location),
initialData:"",
builder: (context, AsyncSnapshot snapshot) {
return Text(
'${snapshot?.data??""}',
style: GoogleFonts.lato(
color: Colors.white70, fontSize: 35.0),
);
}),

I fixed the error by just removing the slidable widget that was wrapping the future builder, don't know why that was causing an error

Related

Infinite Scrolling in GridView.builder

I am Building a flutter e-commerce application. And in the Categories section. There are so much data so I want to implement pagination through infinite scrolling.
This is what I am trying to do, CatHome object is the category either men or women etc.
the code is resulting in pagination, but everytime it is building another page, not infinite scroll. so i cannot access previosly loaded data
class CategoryDetail extends StatefulWidget {
CatHome catHome;
CategoryDetail(this.catHome);
#override
_CategoryDetailstate createState() => _CategoryDetailstate(catHome);
}
class _CategoryDetailstate extends State<CategoryDetail> {
List<FutureOr> _items = [];
CatHome catHome;
_CategoryDetailstate(this.catHome);
var _currentPage = 1;
ScrollController scroll = ScrollController();
var _hasMore = true;
#override
void initState() {
super.initState();
scroll.addListener(() {
if (scroll.position.pixels == scroll.position.maxScrollExtent) {
_fetchMore();
}
});
}
#override
void dispose() {
scroll.dispose();
super.dispose();
}
void _fetchMore() async {
if (_hasMore) {
setState(() {
_currentPage++;
});
var newItems =
await new catitems_api().fetchdeails(catHome, _currentPage);
if (newItems.isEmpty) {
setState(() {
_hasMore = false;
});
} else {
setState(() {
this._items.addAll(newItems);
});
}
}
}
/// Component widget in flashSale layout
Widget build(BuildContext context) {
var data = EasyLocalizationProvider.of(context).data;
return EasyLocalizationProvider(
data: data,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: Text(
AppLocalizations.of(context).tr('Category'),
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 17.0,
color: Colors.black54,
fontFamily: "Gotik"),
),
centerTitle: true,
iconTheme: IconThemeData(color: Color(0xFF6991C7)),
elevation: 0.0,
),
body: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
Container(
key: Key(UniqueKey().toString()),
height: MediaQuery.of(context).size.height * 0.8,
child: FutureBuilder<List<dynamic>>(
future: catitems_api().fetchdeails(catHome, _currentPage),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
}
return GridView.builder(
controller: scroll,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 0.7,
mainAxisSpacing: 8.0,
crossAxisSpacing: 8.0,
),
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
CategoryItems items = snapshot.data[index];
return InkWell(
onTap: () {
new productDet_api()
.fetchdeails(items.id)
.then((itemList) {
Navigator.of(context).push(PageRouteBuilder(
pageBuilder: (_, __, ___) =>
new detailProduk(itemList.first),
transitionDuration:
Duration(milliseconds: 950),
transitionsBuilder: (_flashSaleState,
Animation<double> animation,
__,
Widget child) {
return Opacity(
opacity: animation.value,
child: child,
);
}));
});
},
child: Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.black12.withOpacity(0.1),
spreadRadius: 0.2,
blurRadius: 5.0,
offset: Offset(0.0, 2.0))
]),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.network(
items.image,
width: 150.0,
height: 150.0,
fit: BoxFit.cover,
),
SizedBox(
height: 10.0,
),
Text(
items.name,
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 14.0,
color: Colors.black),
),
SizedBox(
height: 5.0,
),
Text(
"\$" + items.price.toString(),
style: TextStyle(
fontWeight: FontWeight.w600,
fontSize: 14.0,
color: Colors.black),
),
],
),
),
);
},
);
},
),
),
],
),
),
),
),
);
}
}

How to update time dynamically in flutter

I have a list view with list tiles with each containing a region with its specific time.
I am using a Getx controller with the class WorldTime with two parameters location and time.
There is already a timer that's called during setState to update the clock widget, but how do I implement this to update each list tile time or is there any other way to update the time automatically without calling setState.
class _WorldClockState extends State<WorldClock> {
final WorldTimeController worldTimeController =
Get.put(WorldTimeController());
String formattedTime = DateFormat('h:mm').format(DateTime.now());
String hour = DateFormat('a').format(DateTime.now());
late Timer _timer;
#override
void initState() {
super.initState();
_timer =
Timer.periodic(const Duration(milliseconds: 500), (timer) => _update());
}
void _update() {
setState(() {
formattedTime = DateFormat('h:mm').format(DateTime.now());
hour = DateFormat('a').format(DateTime.now());
});
}
#override
void dispose() {
_timer.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
body: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(formattedTime,
style: GoogleFonts.lato(
fontSize: 80.0,
color: Colors.blue,
fontStyle: FontStyle.normal,
letterSpacing: 5.0)),
Padding(
padding: const EdgeInsets.only(top: 40.0, left: 5.0),
child: Text(
hour,
style: GoogleFonts.lato(
color: Colors.blue,
fontSize: 30.0,
),
),
),
],
),
),
Container(
child: Text(
DateFormat('EE, MMM d').format(DateTime.now()),
style: GoogleFonts.lato(
color: Colors.white,
fontSize: 20.0,
letterSpacing: 2.0,
),
),
),
const Padding(
padding: EdgeInsets.only(top: 20.0, left: 30.0, right: 30.0),
child: Divider(
color: Colors.white,
height: 2.0,
),
),
GetBuilder<WorldTimeController>(
id: 'Clockid',
builder: (value) => Container(
height: 600.0,
width: 450.0,
child: Padding(
padding: const EdgeInsets.only(top: 20.0),
child: ListView.builder(
scrollDirection: Axis.vertical,
physics: const BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: worldTimeController.WorldTimeList.length,
itemBuilder: (BuildContext context, index) => Padding(
padding: const EdgeInsets.only(bottom: 18.0),
child: Slidable(
key: UniqueKey(),
startActionPane: ActionPane(
motion: ScrollMotion(),
dismissible: DismissiblePane(onDismissed: () {
worldTimeController.WorldTimeList.removeAt(index);
}),
children: const [],
),
child: ListTile(
leading: Text(
worldTimeController
.WorldTimeList[index].location,
style: GoogleFonts.lato(
color: Colors.white70, fontSize: 25)),
trailing: Text(
'${value.getTime(worldTimeController.WorldTimeList[index].location)}',
style: GoogleFonts.lato(
color: Colors.white70, fontSize: 35.0),
),
),
),
),
),
),
),
),
],
),
),
floatingActionButton: Padding(
padding: const EdgeInsets.only(right: 192.0, bottom: 20.0),
child: FloatingActionButton(
onPressed: () {
Get.to(() => const RegionSelectScreen());
},
child: const Icon(Icons.public),
),
),
),
);
}
}
controller:
class WorldTimeController extends GetxController {
var WorldTimeList = <WorldTime>[].obs;
var newUrl;
var newResponse;
Future<dynamic> getTime(location) async {
newUrl = "http://worldtimeapi.org/api/timezone/${location}";
newResponse = await get(Uri.parse(newUrl));
Map newData = jsonDecode(newResponse.body);
var time = newData['datetime'];
String dateTime = newData["utc_datetime"];
String offset = newData["utc_offset"];
DateTime now = DateTime.parse(dateTime);
now = now.add(Duration(
hours: int.parse(offset.substring(1, 3)),
minutes: int.parse(offset.substring(4))));
update(['Clockid']);
return time = DateFormat.jm().format(now);
}
#override
void onInit() {
List? storedWorldTime = GetStorage().read<List>('WorldTime');
if (storedWorldTime != null) {
WorldTimeList.assignAll(
storedWorldTime.map((e) => WorldTime.fromJson(e)).toList());
}
ever(WorldTimeList, (_) {
GetStorage().write('WorldTime', WorldTimeList.toList());
});
super.onInit();
}
}
In your getXcontroller class you can create function to update the hours and on this function you can add
update(['clockId']);
then in your screen
return GetBuilder<WorldTimeController>(
id: 'clockId',
init: WorldTimeController(), // If is init this line is not necessary
builder: (worldTimeController) => Container(
height: 600.0,
width: 450.0,
child: Padding(
padding: const EdgeInsets.only(top: 20.0),
child: ListView.builder(
scrollDirection: Axis.vertical,
physics: const BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: worldTimeController.WorldTimeList.length,
itemBuilder: (BuildContext context, index) => Padding(
padding: const EdgeInsets.only(bottom: 18.0),
child: Slidable(
key: UniqueKey(),
startActionPane: ActionPane(
motion: ScrollMotion(),
dismissible: DismissiblePane(onDismissed: () {
worldTimeController.WorldTimeList.removeAt(
index);
}),
children: [],
),
child: ListTile(
leading: Text(
'${worldTimeController.WorldTimeList[index].location}',
style: GoogleFonts.lato(
color: Colors.white70, fontSize: 25)),
trailing: Text(
"${worldTimeController.WorldTimeList[index].time}",
style: GoogleFonts.lato(
color: Colors.white70, fontSize: 35.0),
),
),
),
)),
),
),
);
Then even that change something in your function this will refresh all the list inside your clockId.
Try to avoid setState because this method rebuild all the view and when your app grows does't has good performance
Here an example:
https://github.com/alcampospalacios/GetX_UpdateAll_Example

How to Fix List Items are automatically changing their positing in flutter?

I am calling API data inside Listview. builder in flutter but the error I am facing is the items are changing their positions automatically.
For Example, When I load this class for the First Time the arrangement of List items is the same as required but after 30-40 seconds the List items arrangement automatically starts changing, and data showing itself randomly.
I am looking for someone who can help me to fix this issue?
For this purpose here is myClass Code.
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:http/http.dart'as HTTP;
import 'package:worldcup/utils/colors.dart';
class SeriesSchedulePage extends StatefulWidget {
#override
_SeriesSchedulePageState createState() => _SeriesSchedulePageState();
}
class _SeriesSchedulePageState extends State<SeriesSchedulePage> {
List<dynamic> matches = [];
var match;
getSchedule() async {
http.Response response = await http
.get(Uri.parse("https://api.cricket.com.au/matches/2780"));
final Map parseData = await json.decode(response.body.toString());
matches = parseData['matchList']["matches"];
setState(() {
match = matches;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColors.primaryWhite,
appBar: AppBar(
backgroundColor: AppColors.yellow,
elevation: 0,
centerTitle: true,
leading: IconButton(
onPressed: () {
Navigator.pop(context,true);
},
icon: Icon(
Icons.arrow_back,
color: Colors.white,
),
),
title: Text(
'Schedule',
textScaleFactor: 0.9,
style: GoogleFonts.openSans(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 17),
),
),
body: Container(
child: FutureBuilder(
future: getSchedule(),
builder: (context, snapshot) {
if (match == null) {
return Center(
child: CupertinoActivityIndicator(
animating: true, radius: 15));
} else
return ListView.builder(
itemCount: matches.length,
shrinkWrap: true,
reverse: false,
itemBuilder: (context, index) {
if (matches[index]["status"] =="UPCOMING") {
return Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
child: Container(
width: double.infinity,
child: Padding(
padding: EdgeInsets.only(left: 15, top: 7, bottom: 7, right: 15),
child: Row(
children: [
SizedBox(width: 20,),
Expanded(
flex: 2,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
matches[index]['name'].toString(),
textScaleFactor: 0.9,
style: GoogleFonts.openSans(
fontWeight: FontWeight.w700, fontSize: 15),
),
SizedBox(height: 10,),
Text(
matches[index]["homeTeam"]['name'].toString(),
textScaleFactor: 0.9,
style: GoogleFonts.openSans(
fontWeight: FontWeight.w700, fontSize: 15),
),
SizedBox(height: 10,),
Text(
matches[index]["awayTeam"]['name'].toString(),
textScaleFactor: 0.9,
style: GoogleFonts.openSans(
fontWeight: FontWeight.w500, fontSize: 13),
),
],
),
],
),
),
],
),
),
)
);
} else {
return Center(
child: Text("No Upcoming Match in this series"),
);
}
}
);
},
),
)
);
}
}
The issue is because getSchedule() has a setState inside it. When the build method is called, getSchedule() will trigger, and since it is calling setState , the build method is being called again, causing your widgets to continuously rebuild in an infinite loop.
What you need to do is prevent such a loop from happening. I see that you are using FutureBuilder too, that is a solution but your implementation is incorrect.
What you should do is this:
Future<List<dynamic>> getSchedule() async {
http.Response response =
await http.get(Uri.parse("https://api.cricket.com.au/matches/2780"));
final Map parseData = await json.decode(response.body.toString());
var matches = parseData['matchList']["matches"];
return matches;
}
This function returns a Future<List<dynamic>> which your future builder can use to handle the builds. For info on future builder here https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html.
Since you FutureBuilder will react to what is provided by getSchedule() when the future is complete, you do not need to use setState to rebuild.
I have modified your SeriesShedualPage here is the full code:
class SeriesSchedulePage extends StatefulWidget {
#override
_SeriesSchedulePageState createState() => _SeriesSchedulePageState();
}
class _SeriesSchedulePageState extends State<SeriesSchedulePage> {
Future<List<dynamic>> getSchedule() async {
http.Response response =
await http.get(Uri.parse("https://api.cricket.com.au/matches/2780"));
final Map parseData = await json.decode(response.body.toString());
var matches = parseData['matchList']["matches"];
return matches;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: FutureBuilder<List<dynamic>>(
future: getSchedule(),
builder: (context, snapshot) {
if (snapshot.hasData) {
List<dynamic> matches = snapshot.data!;
return ListView.builder(
itemCount: matches.length,
shrinkWrap: true,
reverse: false,
itemBuilder: (context, index) {
if (matches[index]["status"] == "UPCOMING") {
return Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(7),
),
child: Container(
width: double.infinity,
child: Padding(
padding: EdgeInsets.only(
left: 15, top: 7, bottom: 7, right: 15),
child: Row(
children: [
SizedBox(
width: 20,
),
Expanded(
flex: 2,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(
matches[index]['name'].toString(),
textScaleFactor: 0.9,
),
SizedBox(
height: 10,
),
Text(
matches[index]["homeTeam"]['name']
.toString(),
textScaleFactor: 0.9,
),
SizedBox(
height: 10,
),
Text(
matches[index]["awayTeam"]['name']
.toString(),
textScaleFactor: 0.9,
),
],
),
],
),
),
],
),
),
));
} else {
return Center(
child: Text("No Upcoming Match in this series"),
);
}
});
}
return Center(
child: CupertinoActivityIndicator(animating: true, radius: 15));
},
),
));
}
}

How to fetch specific data from API into flutter app

I am a beginner in flutter.
I have created two ListView Builder where one ListView.builder is inside another builder as given below.
I have a list of categories which is inside one listview.builder and other are the list of products which also listview.builder Wrapped inside the above listview build>
So now i need to display the only items belonging to the 1st listview builder which means If I have a categories named soup (1st ListView.builder) Now i need to display only the products that belongs to soup categories from 2nd Listview.Builder but all the products are listed inside all the categories list. So, Please help me to find solution any help would be appriciated.Thank you in advance.
Below are the codes.
//lib/routes/menu_description.dart(File name)
import 'package:flutter/material.dart';
import '../api_service.dart';
import 'package:html/parser.dart';
import 'package:percent_indicator/percent_indicator.dart';
class MenuDescription extends StatefulWidget {
MenuDescription({Key key}) : super(key: key);
#override
_MenuDescriptionState createState() => _MenuDescriptionState();
}
int itemspressed;
class _MenuDescriptionState extends State<MenuDescription> {
#override
Widget build(BuildContext context) {
return Container(
// color: Colors.grey[200],
child: FutureBuilder(
future: fetchWpPosts(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.separated(
separatorBuilder: (context, index) => Divider(
height: 20.0,
color: Colors.black,
),
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Map wpcategoriespost = snapshot.data[index];
return Container(
color: Colors.grey[200],
child: InkWell(
splashColor: Colors.grey[800],
onTap: () {
setState(() {
itemspressed = index;
});
},
child: Padding(
padding: const EdgeInsets.only(
left: 5, right: 5, bottom: 5, top: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Text(
"${wpcategoriespost['name']}",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
color: Colors.lightGreen[900],
),
),
),
Center(
child: Text(
parse(("${wpcategoriespost['description']}")
.toString())
.documentElement
.text,
style:
TextStyle(fontSize: 14, color: Colors.black),
),
),
Container(
padding: EdgeInsets.only(top: 20.0),
child: Categories(),)
],
),
),
),
);
},
);
}
return new CircularPercentIndicator(
radius: 120.0,
lineWidth: 13.0,
animation: true,
percent: 1.0,
progressColor: Colors.orange,
center: new Text(
"100.0%",
style:
new TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0),
));
},
),
);
}
}
class Categories extends StatefulWidget {
#override
_CategoriesState createState() => _CategoriesState();
}
class _CategoriesState extends State<Categories> {
#override
Widget build(BuildContext context) {
return Container(
child: FutureBuilder(
future: fetchWpPosts(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
Map wppost = snapshot.data[index];
return Card(
margin: const EdgeInsets.only(
left: 15,
right: 15,
bottom: 15,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
elevation: 3,
child: InkWell(
splashColor: Colors.grey[300],
onTap: () {
setState(() {
itemspressed = index;
});
},
child: Padding(
padding: const EdgeInsets.only(
left: 12, right: 5, bottom: 12, top: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"${wppost['name']}",
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
color: Colors.lightGreen[900]),
),
Container(
height: 40,
width: 40,
decoration: BoxDecoration(
shape: BoxShape.rectangle,
border: Border.all(color: Colors.grey[350]),
color: itemspressed == index
? Colors.grey[350]
: null,
),
child: IconButton(
iconSize: 22,
icon: Icon(
Icons.add,
color: Colors.blueAccent[400],
),
onPressed: () {
setState(() {});
print('Add to cart');
},
),
),
],
),
Text(
parse(("${wppost['description']}").toString())
.documentElement
.text,
style: TextStyle(fontSize: 14, color: Colors.black),
),
Text(
parse(("${wppost['price']} €").toString())
.documentElement
.text,
style: TextStyle(
fontSize: 15,
color: Colors.amber[700],
fontWeight: FontWeight.bold),
),
],
),
),
),
) ;
},
);
}
return new CircularPercentIndicator(
radius: 120.0,
lineWidth: 13.0,
animation: true,
percent: 1.0,
progressColor: Colors.orange,
center: new Text(
"100.0%",
style:
new TextStyle(fontWeight: FontWeight.bold, fontSize: 20.0),
));
},
),
);
}
}
//lib/api_service.dart
import 'package:http/http.dart' as http;
import 'dart:convert';
Future<List> fetchWpPosts() async{
final response = await http.get('https://word.tkco.in/wp-json/wc/v3/products?consumer_key=ck_94114a31e4576e61a9292f961489e7701029753e&consumer_secret=cs_dd4dc6e7945d8dcd14d888bc1d0ea0806b116dfb');
var convertDatatoJson = jsonDecode(response.body);
if (response.statusCode == 200) {
}
return convertDatatoJson;
}

passing data through the widget constructor

i am missing a small piece of information about constructors, i am trying to pass some data through the widget PromotionCard( [ ... ] ) i can't see any error in my debug console i tried Cards widgets and other different stuff to show the data but i can't find out what is wrong with this code down below.
Note: when i print snapshot.data i can see it perfectly returned
any help please.
**promotions_page.dart**
class PromotionsPage extends StatefulWidget {
#override
_PromotionsPageState createState() => _PromotionsPageState();
}
class _PromotionsPageState extends State<PromotionsPage> {
Future<Result> _promotionsResultsData;
#override
void initState() {
_promotionsResultsData = PromotionApi().fetchPromotions();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
margin: EdgeInsets.symmetric(horizontal: 10.0, vertical: 20.0),
child: ListView(
physics: PageScrollPhysics(),
children: [
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Акции',
style: TextStyle(
fontSize: 18.0,
fontWeight: FontWeight.bold,
fontFamily: 'BuffetBold',
),
),
InkWell(
onTap: () => print('Archive promotion pressed!'),
child: Text(
'Архив Акции',
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
fontFamily: 'BuffetBold',
color: Colors.grey[400],
),
),
),
],
),
SizedBox(
height: 10.0,
),
Container(
child: FutureBuilder<Result>(
future: _promotionsResultsData,
builder: (context, snapshot) {
if (snapshot.hasData) {
return GridView.builder(
padding: EdgeInsets.zero,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
childAspectRatio: (45 / 35),
crossAxisCount: 1,
),
shrinkWrap: true,
physics: ScrollPhysics(),
itemCount: snapshot.data.result.length,
itemBuilder: (BuildContext context, int index) {
//print(snapshot.data.result.length);
var promos = snapshot.data.result[index];
PromotionCard(
id: promos.id,
title: promos.title,
description: promos.description,
image: promos.image);
},
);
} else {}
return Center(
child: Text(
"Loading ...",
style: TextStyle(
fontWeight: FontWeight.w900, fontSize: 30.0),
),
);
},
),
),
],
),
],
),
),
);
}
}
i am trying to pass data to this screen
**w_promotion_card.dart**
class PromotionCard extends StatelessWidget {
final String id;
final String title;
final String description;
final String image;
PromotionCard({this.id, this.title, this.description, this.image});
#override
Widget build(BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
height: 200.0,
margin: EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 10.0),
padding: EdgeInsets.zero,
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(image),
alignment: Alignment.topCenter,
),
borderRadius: BorderRadius.circular(10.0),
border: Border.all(
width: 1.5,
color: Colors.grey[300],
),
),
child: Container(
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.zero,
child: Padding(
padding: EdgeInsets.fromLTRB(10, 170.0, 10.0, 10.0),
child: Text(
title,
style: TextStyle(
fontSize: 16.0,
fontFamily: 'BuffetRegular',
),
),
),
),
);
}
}
You missed the return statement
itemBuilder: (BuildContext context, int index) {
//print(snapshot.data.result.length);
var promos = snapshot.data.result[index];
// you have to return the widget
return PromotionCard(
id: promos.id,
title: promos.title,
description: promos.description,
image: promos.image);
},