After get request, data isn't showing in my screen - flutter

In this code data successfully adding to my ''items'' list.
But In the second code, when I call my ''items'' list, It looks empty. What should I do for displaying data?
import 'dart:convert';
import 'package:http/http.dart' as http;
class IceCream {
final String id;
final String? title;
final String? shortTitle;
final String? description;
final String? longDescription;
final double price;
final String imageUrl;
final double? kilos;
final double? review;
final int? reviewCount;
IceCream(
{required this.id,
this.title,
this.shortTitle,
this.description,
this.longDescription,
required this.price,
required this.imageUrl,
this.kilos,
this.review,
this.reviewCount});
}
class Products {
List<IceCream> _items = [];
List<IceCream> get items {
return [..._items];
}
Future<void> fetchProducts() async {
final url = Uri.parse(
'https://ice-cream-app-31dce-default-rtdb.europe-west1.firebasedatabase.app/icecreams.json');
try {
final response = await http.get(url);
// print(response.body);
final extractedData = json.decode(response.body) as Map<String, dynamic>;
if (extractedData.length == null) {
return;
}
final List<IceCream> loadedProduct = [];
extractedData.forEach((prodId, prodData) {
loadedProduct.add(IceCream(
id: prodId,
title: prodData['title'],
description: prodData['description'],
price: prodData['price'],
imageUrl: prodData['imageUrl'],
shortTitle: prodData['shortTitle'],
longDescription: prodData['longDescription'],
kilos: prodData['kilos'],
review: prodData['review'],
reviewCount: prodData['reviewCount']));
});
_items = loadedProduct;
//print(items);
} catch (error) {
print(error);
throw (error);
}
}
}
Second code:
import 'package:flutter/material.dart';
import 'package:ice_cream_ui_clone/model/ice_cream.dart';
import 'package:ice_cream_ui_clone/screens/detail_screen.dart';
import '../utils/constants.dart';
import 'add_item_button.dart';
class TopFlavoursList extends StatelessWidget {
#override
Widget build(BuildContext context) {
final cart = Products().items;
return Expanded(
flex: 2,
child: ListView.builder(
itemCount: cart.length,
scrollDirection: Axis.horizontal,
itemBuilder: (ctx, i) => GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (ctx) => DetailScreen(
item: cart[i],
)));
},
child: Card(
color: myLightPinkColor,
child: Padding(
padding: EdgeInsets.all(lowPadding),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Image.network(
cart[i].imageUrl,
height: midImageHeight,
width: midImageWidht,
),
SingleChildScrollView(
child: Column(
children: [
Text(cart[i].title!,
style:
Theme.of(context).textTheme.headline5),
SizedBox(
height: lowPadding,
),
Row(
children: [
Text("${cart[i].kilos.toString()} KG",
style: Theme.of(context)
.textTheme
.headline6),
SizedBox(
width: lowImageWidht,
),
Icon(
Icons.star,
color: myYellowColor,
),
Text(cart[i].review.toString(),
style: Theme.of(context)
.textTheme
.headline6)
],
),
Row(
children: [
Text("\$${cart[i].price.toString()}",
style: Theme.of(context)
.textTheme
.headline5),
SizedBox(
width: lowImageWidht,
),
AddItemButton(
buttonShape: const CircleBorder(),
)
],
)
],
),
)
],
)),
),
)),
);
}
}

I think the issue is with the "forEach" statment. Should be something more like
extractedData.forEach((data) {
loadedProduct.add(IceCream())
});
The function in the forEach should take one argument not 2

Related

Is not a subtype of type Flutter

im trying to fetch a news api and display the data in my widget, but im getting this error: _TypeError (type '(dynamic) => Article' is not a subtype of type '(String, dynamic) => MapEntry<dynamic, dynamic>' of 'transform')
this is the function where i fetch the data
import 'dart:convert';
import 'package:http/http.dart' as http;
import '../models/article_model.dart';
const url =
"https://newsapi.org/v2/top-headlines?country=br&apiKey=399c0c22d7c845608909937a974ab209";
Future<List<Article>> getArticle() async {
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
List<Article> articles =
data.map((json) => Article.fromJson(json)).toList();
print(articles);
return articles;
} else {
throw Exception("Failed to get articles");
}
}
this is the model i create to receive an article:
class Article {
final String title;
final String author;
final String description;
final String url;
final String urlToImage;
final String content;
const Article({
required this.title,
required this.author,
required this.description,
required this.url,
required this.urlToImage,
required this.content,
});
factory Article.fromJson(Map<String, dynamic> json) {
return Article(
title: json['title'],
author: json['author'],
description: json['description'],
url: json['url'],
urlToImage: json['urlToImage'],
content: json['content'],
);
}
get article => null;
}
that`s my widget:
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import '../models/article_model.dart';
class ChamadaSuite extends StatelessWidget {
final Article article;
final String title;
final String author;
final String description;
final String url;
final String urlToImage;
final String content;
const ChamadaSuite(
{super.key,
required this.title,
required this.author,
required this.description,
required this.url,
required this.urlToImage,
required this.content,
required this.article});
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(20),
child: Row(
children: [
Container(
width: 110,
height: 90,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
image: const DecorationImage(
fit: BoxFit.cover, image: AssetImage("assets/vasco.png")),
),
),
Flexible(
child: Container(
padding: EdgeInsets.only(left: 15),
width: MediaQuery.of(context).size.width,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
"ESPORTE",
style: TextStyle(
color: Colors.green,
fontSize: 12,
fontWeight: FontWeight.w500,
height: 1.2,
letterSpacing: 0.13,
),
),
Text(
article.title,
style: TextStyle(
color: Colors.black,
fontSize: 16,
fontWeight: FontWeight.bold,
height: 1.4,
letterSpacing: 0.16,
),
)
],
),
),
)
],
),
);
}
}
and this is my homepage.dart, where i call the function to populate the widget:
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import '../api/get_article.dart';
import '../models/article_model.dart';
import '../widgets/manchete_suite_destaque.dart';
import '../widgets/chamada_suite.dart';
class HomePage extends StatefulWidget {
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
List<Tab> tabs = [
const Tab(child: Text('últimas notícias')),
const Tab(child: Text('bahia')),
const Tab(child: Text('política')),
const Tab(child: Text('esportes')),
const Tab(child: Text('últimas notícias')),
const Tab(child: Text('agenda cultural')),
];
#override
void initState() {
super.initState();
}
Future<List<Article>> fetchArticles() async {
return await getArticle();
}
final article = const Article(
author: '',
content: '',
description: '',
title: '',
url: '',
urlToImage: '',
);
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: tabs.length,
child: Scaffold(
appBar: AppBar(
leadingWidth: 100,
leading: Padding(
padding: const EdgeInsets.only(left: 10.0),
child: SvgPicture.asset('assets/ibahia.svg'),
),
actions: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.search),
),
IconButton(
onPressed: () {},
icon: const Icon(Icons.menu),
),
],
bottom: PreferredSize(
preferredSize: const Size.fromHeight(30),
child: TabBar(
indicatorColor: Colors.white,
isScrollable: true,
tabs: tabs,
)),
),
body: FutureBuilder<List<Article>>(
future: fetchArticles(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context, index) {
Article article = snapshot.data![index];
return SingleChildScrollView(
child: Column(
children: [
const MancheteSuiteDestaque(),
ChamadaSuite(
title: article.title,
author: article.author,
content: article.content,
description: article.description,
url: article.url,
urlToImage: article.urlToImage,
article: article.article,
),
],
),
);
});
} else if (snapshot.hasError) {
return Text(snapshot.error.toString());
} else {
return const CircularProgressIndicator();
}
},
),
),
);
}
}
How can i solve this error? i dont even know where its the error
Specify a type when calling map method, for example: map<Article>.
In your code, change:
List<Article> articles =
data.map((json) => Article.fromJson(json)).toList();
To:
List<Article> articles =
data.map<Article>((json) => Article.fromJson(json)).toList();
By the way, depending on your Dart version, you may be able to write this instead:
List<Article> articles =
data.map<Article>(Article.fromJson).toList();

How can I map a JSON map to single key multiple values

This might be a bit of broad question.
I have an JSON Map Array which i can parse normally. But i would like to MAP multiple Values to a Single key. I am stuck and unsure how to proceed.
My JSON output. I cannot change this.
{
"pos":"1",
"element":"37542",
"title":"Easy On Me",
"inter":"Adele",
"isnew":"0"
},
{
"pos":"66",
"element":"37183",
"title":"Send My Love",
"inter":"Adele",
"isnew":"0"
}
this is just a snippet of the actual JSON objects
what I would like to do is something like Map<String,List<String,String>>
Adele
Easy On Me, 37542
Send My Love, 37183
Searching online I find a lot of examples how to parse JSON normally, but never found a version where you can iterate through a JSON version like above and pull parts of the map out and add it to another.
any help would be appreciated. Thank you in advance
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'dart:async';
class SongList {
final List<Song> songs;
SongList({
required this.songs,
});
factory SongList.fromJson(List<dynamic> parsedJson) {
List<Song> songs = <Song>[];
songs = parsedJson.map((i) => Song.fromJson(i)).toList();
return SongList(songs: songs);
}
}
class Song {
final String? pos;
final String? element;
final String? title;
final String? inter;
final String? isnew;
const Song(
{required this.pos,
required this.element,
required this.title,
required this.inter,
required this.isnew});
factory Song.fromJson(Map<String, dynamic> data) {
return Song(
pos: data['pos'] as String?,
element: data['element'] as String?,
title: data['title'] as String?,
inter: data['inter'] as String?,
isnew: data['isnew'] as String?,
);
}
}
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
class Songs extends StatefulWidget {
final String pos;
final String element;
final String title;
final String inter;
final String isnew;
const Songs(
{super.key,
required this.pos,
required this.element,
required this.title,
required this.inter,
required this.isnew});
#override
State<Songs> createState() => _SongsState();
}
class _SongsState extends State<Songs> {
late AudioPlayer player;
#override
void initState() {
super.initState();
player = AudioPlayer();
}
#override
void dispose() {
player.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
var titles = Row(
mainAxisSize: MainAxisSize.min,
children: [
Column(children: [
SizedBox(
height: 25,
width: 200,
child: Text(
widget.title,
style: const TextStyle(fontSize: 14),
textAlign: TextAlign.center,
),
),
SizedBox(
height: 25,
width: 200,
child: Text(
widget.inter,
style: const TextStyle(fontSize: 10),
textAlign: TextAlign.center,
),
),
]),
],
);
return FittedBox(
fit: BoxFit.contain,
child: Card(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
Center(
child: SizedBox(
height: 50,
width: 50,
child: Align(
alignment: Alignment.center,
child: widget.isnew != "1"
? Text(
widget.pos.toString(),
textAlign: TextAlign.center,
)
: const Text(
"new",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.red),
)))),
],
),
Column(
children: [
SizedBox(
height: 50,
width: 50,
child: Image.network(
'${'http://www.example.com/${widget.element}'}.jpg'),
),
],
),
Column(
children: [
titles,
],
),
Column(
children: [
SizedBox(
height: 50,
width: 50,
child: TextButton(
onPressed: () async {
final url =
'${'http://www.example.com/${widget.element}'}.mp3';
await player.setUrl(url);
player.play();
},
child: Image.asset('assets/images/btn_play.png'),
),
),
],
),
Column(
children: [
SizedBox(
height: 50,
width: 50,
child: TextButton(
// ignore: avoid_print
onPressed: () =>
print('pressed button download!! ${widget.element}'),
child: Image.asset('assets/images/btn_download.png'),
),
),
],
),
],
)));
}
}
Future<SongList> fetchSong() async {
final response = await http
.get(Uri.parse('http://example.com'));
if (response.statusCode == 200) {
return SongList.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to Load Songs');
}
}
//snippet from class that instatiates
late Future<SongList> futureSong;
#override
void initState() {
super.initState();
futureSong = fetchSong();
}
//snippet from class that builds the list
FutureBuilder<SongList>(
future: futureSong,
builder: (context, AsyncSnapshot<SongList> snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data!.songs.length,
itemBuilder: (context, index) {
if (snapshot.data!.songs[index].element.toString() !=
"null") {
return Songs(
element:
snapshot.data!.songs[index].element.toString(),
inter: snapshot.data!.songs[index].inter.toString(),
isnew: snapshot.data!.songs[index].isnew.toString(),
pos: snapshot.data!.songs[index].pos.toString(),
title: snapshot.data!.songs[index].title.toString());
} else {
return const SizedBox(height: 0);
}
});
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
// By default, show a loading spinner.
return const CircularProgressIndicator();
}
This might work:
void main() {
var data=[
{
"pos":"1",
"element":"37542",
"title":"Easy On Me",
"inter":"Adele",
"isnew":"0"
},
{
"pos":"66",
"element":"37183",
"title":"Send My Love",
"inter":"Adele",
"isnew":"0"
},
{
"pos":"80",
"element":"5000",
"title":"Enjoy the silence",
"inter":"Depeche Mode",
"isnew":"0"
},
{
"pos":"100",
"element":"6000",
"title":"In your room",
"inter":"Depeche Mode",
"isnew":"0"
}
];
var result = <String,List<Map<String,String>>>{};
for (var d in data) {
print(d);
var e={"element":d["element"]!, "title": d["title"]!};
var key=d["inter"]!;
if (result.containsKey(key)) {
result[key]!.add(e);
} else {
result[key]=[e];
}
}
print(result);
}
You can achieve this by creating a subclass.
Interpret interpretFromJson(String st) => Interpret.fromJson(json.decode(st));
class Interpret{
Interpret({
required this.name,
required this.titles,
});
final String name;
final List<Title> titles;
factory Interpret.fromJson(Map<String, dynamic> json) => Title(
name: json["inter"],
titles: List<Title>.from(json.map((x) => Title.fromJson(x))),
);
}
class Title {
Title({
required this.name,
required this.element,
});
final String name;
final double element;
factory Title.fromJson(Map<String, dynamic> json) => Title(
name: json["name"],
element: json["element"],
);
Then you can just call it like.
InterpretFromJson(json);

How to do infinite scrolling in flutter?

I want to scroll infinitely as much my product has. I have total 412 pages. When I scroll to the end I want to show more item of next pages. that means infinite scrolling. how to do this? i have implemented the ScrollController.
this is my Api:
https://www.moharaj.com.bd/api/new/collection/products?page=1
this is my model class:
// To parse this JSON data, do
//
// final newCollectionProductModel = newCollectionProductModelFromJson(jsonString);
import 'dart:convert';
NewCollectionProductModel newCollectionProductModelFromJson(String str) =>
NewCollectionProductModel.fromJson(json.decode(str));
String newCollectionProductModelToJson(NewCollectionProductModel data) =>
json.encode(data.toJson());
class NewCollectionProductModel {
NewCollectionProductModel({
required this.currentPage,
required this.data,
required this.firstPageUrl,
required this.from,
required this.lastPage,
required this.lastPageUrl,
required this.nextPageUrl,
required this.path,
required this.perPage,
required this.prevPageUrl,
required this.to,
required this.total,
});
final int currentPage;
final List<Datum> data;
final String firstPageUrl;
final int from;
final int lastPage;
final String lastPageUrl;
final String nextPageUrl;
final String path;
final int perPage;
final dynamic prevPageUrl;
final int to;
final int total;
factory NewCollectionProductModel.fromJson(Map<String, dynamic> json) =>
NewCollectionProductModel(
currentPage: json["current_page"],
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
firstPageUrl: json["first_page_url"],
from: json["from"],
lastPage: json["last_page"],
lastPageUrl: json["last_page_url"],
nextPageUrl: json["next_page_url"],
path: json["path"],
perPage: json["per_page"],
prevPageUrl: json["prev_page_url"],
to: json["to"],
total: json["total"],
);
Map<String, dynamic> toJson() => {
"current_page": currentPage,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
"first_page_url": firstPageUrl,
"from": from,
"last_page": lastPage,
"last_page_url": lastPageUrl,
"next_page_url": nextPageUrl,
"path": path,
"per_page": perPage,
"prev_page_url": prevPageUrl,
"to": to,
"total": total,
};
}
class Datum {
Datum({
required this.id,
required this.name,
required this.price,
required this.salePrice,
required this.slug,
required this.discount,
required this.thumnail,
required this.productImage,
});
final int id;
final String name;
final String price;
final String salePrice;
final String slug;
final int discount;
final String thumnail;
final List<ProductImage> productImage;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
id: json["id"],
name: json["name"],
price: json["price"],
salePrice: json["sale_price"],
slug: json["slug"],
discount: json["discount"],
thumnail: json["thumnail"],
productImage: List<ProductImage>.from(
json["product_image"].map((x) => ProductImage.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"price": price,
"sale_price": salePrice,
"slug": slug,
"discount": discount,
"thumnail": thumnail,
"product_image":
List<dynamic>.from(productImage.map((x) => x.toJson())),
};
}
class ProductImage {
ProductImage({
required this.id,
required this.productId,
required this.productImage,
required this.createdAt,
required this.prefixUrl,
required this.updatedAt,
});
final int id;
final int productId;
final String productImage;
final DateTime createdAt;
final String prefixUrl;
final DateTime updatedAt;
factory ProductImage.fromJson(Map<String, dynamic> json) => ProductImage(
id: json["id"],
productId: json["product_id"],
productImage: json["product_image"],
createdAt: DateTime.parse(json["created_at"]),
prefixUrl: json["prefix_url"],
updatedAt: DateTime.parse(json["updated_at"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"product_id": productId,
"product_image": productImage,
"created_at": createdAt.toIso8601String(),
"prefix_url": prefixUrl,
"updated_at": updatedAt.toIso8601String(),
};
}
this is my Service class Code:
import 'dart:convert';
import 'package:infinite_pagination/NewArrival.dart';
import 'package:infinite_pagination/NewCollectionProductModel.dart';
import 'package:http/http.dart' as http;
/**
* This is a Service Class.
* This Service Class is used for New COllection Product.
*
*/
class NewCollectionProductService {
static var product;
static Future<NewCollectionProductModel>
getNewCollectionProductService() async {
try {
final response = await http.get(Uri.parse(
"https://www.moharaj.com.bd/api/new/collection/products?page=$pageNumber"));
//print(response);
if (response.statusCode == 200 || response.statusCode == 201) {
final decode = jsonDecode(response.body);
product = NewCollectionProductModel.fromJson(decode);
return product;
} else {
return product;
}
} catch (error) {
throw Exception();
}
}
}
this is product Class:
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
var size = 180.0;
var iconSize = 10.0;
Widget Products(String ImgLocation, name, price, discountPrice, discountPercent,
reviews, BuildContext context) {
return Container(
height: 300,
child: Card(
child: Padding(
padding: EdgeInsets.all(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.network(
'$ImgLocation',
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
return loadingProgress == null
? child
: Center(
child: LinearProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null,
));
// : LinearProgressIndicator();
},
width: MediaQuery.of(context).size.width,
height: size,
),
),
),
Text(
'$name',
textAlign: TextAlign.start,
),
Text(
'৳ $price',
style: TextStyle(
fontSize: 15,
color: Colors.red,
fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
Text.rich(
TextSpan(
children: <TextSpan>[
// ignore: unnecessary_new
TextSpan(
text: '৳ $discountPercent',
style: const TextStyle(
color: Colors.grey,
decoration: TextDecoration.lineThrough,
),
),
TextSpan(
text: ' -$discountPrice%',
),
],
),
),
Row(
children: [
Icon(
Icons.star,
color: Color(0xFFFfebf50),
size: iconSize,
),
Icon(
Icons.star,
color: Color(0xFFFfebf50),
size: iconSize,
),
Icon(
Icons.star,
color: Color(0xFFFfebf50),
size: iconSize,
),
Icon(
Icons.star,
color: Color(0xFFFfebf50),
size: iconSize,
),
Icon(
Icons.star,
color: Color(0xFFFfee9c3),
size: iconSize,
),
SizedBox(
width: 5,
),
Text(
'($reviews)',
style: TextStyle(fontSize: iconSize),
)
],
)
],
)),
),
);
}
this is my home page:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:infinite_pagination/NewArrivalController.dart';
import 'package:infinite_pagination/NewCollectionProductModel.dart';
import 'package:infinite_pagination/NewCollectionProductService.dart';
import 'package:infinite_pagination/Products.dart';
//------------------------------------------------------------
// this widget is for Upcoming categories
//------------------------------------------------------------
class NewArrival extends StatefulWidget {
#override
State<NewArrival> createState() => _NewArrivalState();
}
var pageNumber = 1;
class _NewArrivalState extends State<NewArrival> {
NewArrivalController newArrivalController = Get.put(NewArrivalController());
late Future<NewCollectionProductModel> getData;
ScrollController scrollController = ScrollController();
#override
void initState() {
getData = NewCollectionProductService.getNewCollectionProductService();
// TODO: implement initState
super.initState();
scrollController.addListener(() {
print(scrollController.position.pixels);
if (scrollController.position.pixels ==
scrollController.position.maxScrollExtent) {
pageNumber++;
print(pageNumber);
}
});
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
scrollController.dispose();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Padding(
padding: EdgeInsets.only(left: 10),
child: Text('New Arrival',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.bold,
)),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: MaterialButton(
color: Colors.red,
child: Text("View All"),
onPressed: () {}),
)
],
),
Container(
// height: 200,
child: collectionOfData())
],
),
),
),
);
}
collectionOfData() {
return FutureBuilder<NewCollectionProductModel>(
future: getData,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
controller: scrollController,
physics: NeverScrollableScrollPhysics(),
// scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: snapshot.data!.data.length,
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: 2),
itemBuilder: (context, int index) {
var product = snapshot.data!.data[index];
//slug = product.slug;
String image = product.productImage[0].prefixUrl.toString() +
product.productImage[0].productImage.toString();
return GestureDetector(
onTap: () {},
child: Container(
height: 300,
width: 200,
child: Products(
image,
product.name,
product.price,
product.discount,
product.salePrice,
product.id,
context,
),
),
);
});
} else {
return Center(child: CircularProgressIndicator());
}
});
}
}
you can manage in 2 ways.
without package: manage scrolling point & total page, current page & per page items.
using pagination_view and other packages.
you can also check the below links.
raywenderlich-pagination
mobikul-pageination
stack-overfllow-query
Simple Example without packages:
Declare the below code initially.
ScrollController _scrollController = new ScrollController();
var pageNumber = 1;// update in API CALL
total_page = 0; // update in API CALL
current_page = 0; // update in API CALL
List<ModelClass> arrList = [];
Add below code init method
_scrollController.addListener(() async {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
if (currentPage != total) { // on bottom scroll API Call until last page
currentPage += 1;
apiCall(page: currentPage);
}
}
});
If No data is found & add Pull to refresh widget.
Widget noDataFound() {
return RefreshIndicator(
onRefresh: apiCall(),
child: Center(
child: Text('No Data Found!'),
),
);
}
in Build Widget
arrList.isNotEmpty ? ListView.separated(
padding: const EdgeInsets.all(16.0),
separatorBuilder: (c, index) {
return SizedBox(
height: 20.0,
);
},
physics: AlwaysScrollableScrollPhysics(),
controller: _scrollController,
itemCount: arrList.size + 1,
itemBuilder: (_, index) {
if (index == arrList.length) { // Always one widget 'Loading...' added end of list it will Hide/Show based on condtion.
return Visibility(
visible:
current_page != totalPage ? false:true,
child: Center(
child: Text('Loading...',),
);
} else {
return ... listViewItemWidget;
}
}) : noDataFound()
API Call Function
apiCall(int page = 0){
// update all pagenation variables After API get & map data sucessfully
currentPage , Total page , list value
// Add one condition to store data
if (page == 0) { // If Pull to refresh.
arrList.clear();
arrList = [mapData list from API]; // New data load.
} else {
arrList.add([mapData list from API]); // Append new data in old list
}
}
You can look at the infinite_scroll_pagination package
You can use custom ScrollController to listen when to load more items:
import 'package:flutter/widgets.dart';
class InfiniteListenerController extends ScrollController {
final VoidCallback? onLoadMore;
InfiniteListenerController({this.onLoadMore}) {
if(onLoadMore != null) addListener(_endListener);
}
void _endListener() {
if (position.pixels == position.maxScrollExtent) {
onLoadMore?.call();
}
}
#override
void dispose() {
if(onLoadMore != null) removeListener(_endListener);
super.dispose();
}
}

How to read nested data with firestore in flutter?

I am display a list of products, searched plenty of articles and tutorials but didn't succeeded to display the list of units fetched from the firestore and the specific price of the unit from firestore. kindly help me to achieve it.
I want to display the unit in a dropdown list and the assigned price according to the unit, but unable to do so, as i am new to flutter and trying to do code with the help of tutorials.
product.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class Product with ChangeNotifier {
final String id;
final String title;
final String description;
final String imageUrl;
final String productCategoryName;
Product({
required this.id,
required this.title,
required this.description,
required this.imageUrl,
required this.productCategoryName,
});
}
class ProductProvider with ChangeNotifier {
List<Product> _products = [];
Future<void> fetchProducts() async {
await FirebaseFirestore.instance
.collection('products')
.get()
.then((QuerySnapshot productSnapshot) {
_products = [];
for (var element in productSnapshot.docs) {
_products.insert(
0,
Product(
id: element.data()['productId'],
title: element.data()['productTitle'],
description: element.data()['productDescription'],
imageUrl: element.data()['productImage'],
productCategoryName: element.data()['productCategory'],
),
);
}
});
}
List<Product> products() => _products;
List<Product> getByCatName(String catName) {
List<Product> catList = _products
.where((element) =>
element.productCategoryName.toLowerCase() == catName.toLowerCase())
.toList();
return catList;
}
Product getById(String prodId) {
return _products.firstWhere((element) => element.id == prodId);
}
List<Product> getBySearch(String search) {
List<Product> prodList = _products
.where((element) =>
element.title.toLowerCase().contains(search.toLowerCase()))
.toList();
notifyListeners();
return prodList;
}
}
feed_product.dart
import 'dart:io';
import 'package:badges/badges.dart';
import 'feed_product_dialog.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../models_providers/product.dart';
import '../screens/inner_screens/product_details_screen.dart';
class FeedsProduct extends StatefulWidget {
const FeedsProduct({Key? key}) : super(key: key);
#override
_FeedsProductState createState() => _FeedsProductState();
}
class _FeedsProductState extends State<FeedsProduct> {
String unitValue = '1kg';
late Product product;
#override
Widget build(BuildContext context) {
final productAttribute = Provider.of<Product>(context);
return InkWell(
onTap: () {
Navigator.of(context).pushNamed(
ProductDetailsScreen.routeName,
arguments: productAttribute.id,
);
},
child: Stack(
children: \[
Container(
height: 300,
decoration: BoxDecoration(
border: Border.all(width: 1, color: Colors.black),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: \[
Center(
child: Container(
constraints: BoxConstraints(
minHeight: Platform.isIOS ? 170 : 140,
maxHeight: MediaQuery.of(context).size.height * 0.21),
child: Center(
child: Image.network(productAttribute.imageUrl,
fit: BoxFit.cover),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: \[
Text(
productAttribute.title,
maxLines: 1,
style: const TextStyle(
fontSize: 16,
overflow: TextOverflow.ellipsis,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: \[
DropdownButton<String>(
value: unitValue,
elevation: 16,
style: const TextStyle(color: Colors.black),
onChanged: (String? newValue) {
setState(() {
unitValue = newValue!;
});
},
items: <String>\['500gm', '1kg'\]
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
),
IconButton(
onPressed: () async {
return showDialog(
context: context,
builder: (ctx) => FeedsProductDialog(
product: productAttribute,
),
);
},
icon: const Icon(Icons.more_horiz),
),
\],
),
\],
),
)
\],
),
),
Badge(
toAnimate: true,
animationType: BadgeAnimationType.slide,
shape: BadgeShape.square,
badgeColor: Colors.deepOrange,
borderRadius: BorderRadius.circular(8),
badgeContent:
const Text('New', style: TextStyle(color: Colors.white)),
),
\],
),
);
}
}

Failed assertion: line 1916 pos 14: 'children != null': is not true.?

I have been trying to run a flutter app and it keeps giving me Failed assertion error. below is my code. I just want to show the list the second code
class Post extends StatefulWidget {
final String postId;
final String ownerId;
final String username;
final String location;
final String description;
final String mediaUrl;
final dynamic likes;
Post({
this.postId,
this.ownerId,
this.username,
this.location,
this.description,
this.mediaUrl,
this.likes,
});
factory Post.fromDocument(DocumentSnapshot doc) {
return Post(
postId: doc['postId'],
ownerId: doc['ownerId'],
username: doc['username'],
location: doc['location'],
description: doc['description'],
mediaUrl: doc['mediaUrl'],
likes: doc['likes'],
);
}
int getLikeCount(likes) {
// if no likes, return 0
if (likes == null) {
return 0;
}
int count = 0;
// if the key is explicitly set to true, add a like
likes.values.forEach((val) {
if (val == true) {
count += 1;
}
});
return count;
}
#override
_PostState createState() => _PostState(
postId: this.postId,
ownerId: this.ownerId,
username: this.username,
location: this.location,
description: this.description,
mediaUrl: this.mediaUrl,
likes: this.likes,
likeCount: getLikeCount(this.likes),
);
}
class _PostState extends State<Post> {
final String postId;
final String ownerId;
final String username;
final String location;
final String description;
final String mediaUrl;
Int likeCount;
Map likes;
_PostState({
this.postId,
this.ownerId,
this.username,
this.location,
this.description,
this.mediaUrl,
this.likes,
this.likeCount,
});
Widget postingHeading() {
return FutureBuilder(
future:
FirebaseFirestore.instance.collection('User').doc(ownerId).get(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
return ListTile(
onTap: () => print('go check the url'),
leading: CircleAvatar(
backgroundImage:
NetworkImage("${snapshot.data.data()['photoUrl']}"),
),
title: Text('${snapshot.data.data()['username']}'),
subtitle: Text(location),
trailing: IconButton(
onPressed: () => print('deleting post'),
icon: Icon(Icons.more_vert),
),
);
});
}
Widget postImagePicture() {
return Stack(
alignment: Alignment.center,
children: [
Image.network(mediaUrl),
],
);
}
Widget postDetailsComment() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
IconButton(icon: Icon(Icons.favorite_border), onPressed: () {}),
IconButton(icon: Icon(Icons.favorite_border), onPressed: () {})
],
),
Row(
children: <Widget>[
Container(
margin: EdgeInsets.only(left: 20.0),
child: Text(
"$likeCount likes",
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
],
),
Row(
children: [
Text(username),
SizedBox(
width: 1,
),
Flexible(child: Text(description))
],
)
],
);
}
#override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
postingHeading(),
postImagePicture(),
postDetailsComment(),
],
);
}
}
here is where I convert it to List... I don't even no what is wrong.... please help.... thanks in advance
class Profile extends StatefulWidget {
final String currentUser;
Profile({this.currentUser});
#override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
final _firestore = FirebaseFirestore.instance;
int postLenght;
List<Post> post;
bool pleaseWait;
#override
void initState() {
super.initState();
getUsersPicsDetails();
}
getUsersPicsDetails() async {
setState(() {
pleaseWait = false;
});
QuerySnapshot _getPost = await _firestore
.collection('post')
.doc(widget.currentUser)
.collection('userPost')
.orderBy('timeStamp', descending: true)
.get();
setState(() {
pleaseWait = true;
postLenght = _getPost.docs.length;
post = _getPost.docs.map((e) => Post.fromDocument(e)).toList();
print(postLenght);
});
}
fellowEditButtton({String test, Function press}) {
return TextButton(
onPressed: press,
child: Container(
alignment: Alignment.center,
height: 25,
width: 250,
decoration: BoxDecoration(
color: Theme.of(context).primaryColor,
border: Border.all(),
borderRadius: BorderRadius.circular(8.0)),
child: Text(
test,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
)),
);
}
gettingUserprofile() {
return StreamBuilder(
stream: _firestore.collection('User').doc(widget.currentUser).snapshots(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(child: CircularProgressIndicator());
}
if (snapshot.connectionState != ConnectionState.active) {
return Text('this stuff en');
}
return ListView.builder(
itemCount: 1,
itemBuilder: (context, index) => Container(
padding: EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
FullScreenWidget(
child: Hero(
tag: 'smallImage',
child: CircleAvatar(
backgroundImage: NetworkImage(
'${snapshot.data.data()['photoUrl']}'),
radius: 50.0,
),
),
),
Expanded(
flex: 1,
child: Column(
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceEvenly,
children: [
topColum(buttom: 'Post', number: 1),
topColum(buttom: 'Fellowers', number: 2),
topColum(buttom: 'Following', number: 0),
],
),
Column(
crossAxisAlignment:
CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20.0,
),
child: widget.currentUser ==
_auth.currentUser.uid
? fellowEditButtton(
test: 'Edit Profile',
press: profileEditingButton)
: fellowEditButtton(
test: 'Fellow', press: () {})),
],
),
],
),
),
],
),
Divider(),
//! this is i call the list
//getUserPicture(),
getUserPicture(),
],
),
));
},
);
}
profileEditingButton() {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => EditProfile(
userProfile: widget.currentUser,
)));
}
Widget topColum({int number, String buttom}) {
return Column(
children: [
Text(
'$number',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
Text(
buttom,
style: TextStyle(
fontSize: 20,
),
),
],
);
}
//! this is the where i return the list
Widget getUserPicture() {
if (pleaseWait = false) {
return CircularProgressIndicator();
}
return Column(
children: post,
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: header(context, titleString: "Profile"),
body:
//Text('${widget.currentUser}')
gettingUserprofile());
// userPictursPost(),
}
}
I want to the get the post at the bottom... thanks in advance
below is the error image
enter image description here
When you get an error, please post it along with your question. When you are getting an error, it means that something is wrong with your code,and most likely not the flutter engine. Both are important for debugging, the error+your code.
Try changing this
QuerySnapshot _getPost = await _firestore
.collection('post')
.doc(widget.currentUser)
.collection('userPost')
.orderBy('timeStamp', descending: true)
.get();
setState(() {
pleaseWait = true;
postLenght = _getPost.docs.length;
post = _getPost.docs.map((e) => Post.fromDocument(e)).toList();
print(postLenght);
});
into this:
QuerySnapshot _getPost = await _firestore
.collection('post')
.doc(widget.currentUser)
.collection('userPost')
.orderBy('timeStamp', descending: true)
.get();
if(_getPost.docs.isNotEmpty){
List<Post> tempPost = _getPost.docs.map((e) => Post.fromDocument(e)).toList();
setState(() {
pleaseWait = true;
post =tempPost
print(postLenght);
});
}else{
print('The List is empty);}
You are not checking if the Query result has data or not. If it's empty, you will pass an empty List post down your tree, and you will get the error you are having.
For people facing similar issues, let me tell what I found in my code:
The error says that the children is null, not empty !
So if you are getting the children for the parent widget like Row or Column from a separate method, just check if you are returning the constructed child widget from the method.
Row(
children: getMyRowChildren()
)
.
.
.
getMyRowChildren(){
Widget childWidget = ... //constructed
return childWidget; //don't forget to return!
}
Else it would return null, which results in the children being null and we get the mentioned above error!