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);
Related
I tried to get data from firestore but display this error "The instance member 'mapRecords' can't be accessed in an initializer. " on Flutter.
Screenshots of errors
https://drive.google.com/drive/folders/1toBdn9h4-LgBLl5ybG63brgXmk5G0h3F?usp=sharing
my code
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hexcolor/hexcolor.dart';
import 'package:kathana/utils/config.dart';
import '../screens/wordsBefore18/database/words12model.dart';
class uitry5 extends StatefulWidget {
const uitry5({Key? key}) : super(key: key);
#override
State<uitry5> createState() => _uitry5State();
}
class _uitry5State extends State<uitry5> {
List<String> wordList = [];
Future _fetch = Future(() async {
var records = await FirebaseFirestore.instance.collection('12words').get();
return mapRecords(records);
});
List<Words12> mapRecords(QuerySnapshot<Map<String, dynamic>> records) {
var wordList = records.docs
.map(
(words12) {
print(words12);
return
Words12(
id: words12.id,
wordName: words12['wordName'],
categoryName: words12['categoryName']
);}
.toList();
return wordList;
}
#override
void initState() {
super.initState();
print(wordList);
}
List<String> selectedWord = [];
List<String>? deSelectedWord = [];
#override
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;
return Scaffold(
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(Config.app_background4), fit: BoxFit.fill),
),
child: SafeArea(
child: Center(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 14, right: 0),
child: Column(
children: [
SizedBox(
width: width * 0.94,
height: height * 0.30,
child: Column(
children: <Widget>[
const SizedBox(height: 16),
Wrap(
children: wordList.map(
(word) {
bool isSelected = false;
if (selectedWord!.contains(word)) {
isSelected = true;
}
return GestureDetector(
onTap: () {
if (!selectedWord!.contains(word)) {
if (selectedWord!.length < 50) {
selectedWord!.add(word);
deSelectedWord!.removeWhere(
(element) => element == word);
setState(() {});
print(selectedWord);
}
} else {
selectedWord!.removeWhere(
(element) => element == word);
deSelectedWord!.add(word);
setState(() {
// selectedHobby.remove(hobby);
});
print(selectedWord);
print(deSelectedWord);
}
},
child: Container(
margin: const EdgeInsets.symmetric(
horizontal: 5, vertical: 4),
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 5, horizontal: 12),
decoration: BoxDecoration(
color: isSelected
? HexColor('#0000FF')
: HexColor('#D9D9D9'),
borderRadius:
BorderRadius.circular(18),
border: Border.all(
color: isSelected
? HexColor('#0000FF')
: HexColor('#D9D9D9'),
width: 2)),
child: Text(
word,
style: TextStyle(
color: isSelected
? Colors.black
: Colors.black,
fontSize: 14,
fontWeight: FontWeight.w600),
),
),
),
);
},
).toList(),
),
],
),
),
],
),
),
],
))),
),
);
}
}
model
import 'dart:convert';
Words12 words12FromJson(String str) => Words12.fromJson(json.decode(str));
String words12ToJson(Words12 data) => json.encode(data.toJson());
class Words12 {
Words12({
required this.id,
required this.wordName,
required this.categoryName,
});
String id;
String wordName;
String categoryName;
factory Words12.fromJson(Map<String, dynamic> json) => Words12(
id: json["id"],
wordName: json["wordName"],
categoryName: json["categoryName"],
);
Map<String, dynamic> toJson() => {
"id": id,
"wordName": wordName,
"categoryName": categoryName,
};
}
How do I resolve this and get data from the database
You can use late before future.
late Future _fetch = ...
Also I will prefer shifting mapRecords before _fetch and FutureBuilder for future.
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();
}
}
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
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!
I am trying to create dynamically rows widget inside column widget. I am new to flutter, I tried my best but still failed to fixed the issue. I would like to request you please help me in this issue. I added all stuff which I tried. Thank you so much
My Json
{
"status": true,
"data": {
"id": 1,
"image": "https://img.taste.com.au/fruCLEZM/taste/2019/08/chicken-karahi-153167-2.jpg",
"calories": 100,
"ingredients_count": 5,
"serve": 1,
"views": 1,
"time": 1,
"translate": {
"post_title": "Chicken Karahi",
"post_description": "spicy and tasteful chicken karahi."
},
"ingredients": [
{
"name": "yogurt",
"quantity": "1 cup",
"image": "https://www.archanaskitchen.com/images/archanaskitchen/BasicRecipes_HOW_TO/How_To_Make_Fresh_Homemade_Yogurt_Curd_400.jpg"
},
{
"name": "red chilli",
"quantity": "100 gram",
"image": "https://ik.imagekit.io/91ubcvvnh3k/tr:w-500/https://www.planetorganic.com//images/products/medium/26148.jpg"
}
]
}
}
Image for refrence
I am facing two errors, which are following,
Another exception was thrown: type '(dynamic) => dynamic' is not a subtype of type '(Ingredient) => Widget' of 'f'
and
type 'Container' is not a subtype of type 'List<Widget>'
In my statefull class I have following
var posts;
bool _load = false;
void initState() {
super.initState();
getRecipeById().then((value) => {
setState((){
posts = value;
})
});
}
and by this method I am getting data from api
getRecipeById() async {
String url = 'http://www.xxxxx.com/xxxxx/in.php';
Map<String, String> requestHeaders = {
'Content-type': 'application/json',
'Accept': '*/*',
};
final json = {
"by_post_id": 'yes',
"post_id":'${widget.postId}'
};
http.Response response = await http.post(url, body: json);
if(response.statusCode == 200){
setState(() {
_load = true;
});
}
var jsonResponse = jsonDecode(response.body);
posts = RecipeModel.fromJson(jsonResponse['data']);
return posts;
}
Following is my build widget
Widget build(BuildContext context) {
final ingredientsList = Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.only(left: 1.0, right: 25.0),
margin: const EdgeInsets.only(bottom: 20.0),
child: Container(
child: Column(
children: (_load == false) ? Container(child:Text("loading..")) : posts.ingredients.map<Widget>((data) =>
ingredientsRow(data.name, data.quantity, data.image)
).toList(),
),
),
);
return SafeArea(
top: true,
child: Scaffold(
body: Directionality(
textDirection: TextDirection.ltr,
child: SingleChildScrollView(
child: (_load == false) ? Container(
alignment: Alignment.center,
child: Text("loading now..")
) :
Column(
children: <Widget>[
ingredientsList,
],
),
),
),
)
);
}
and following is function which I want to use in map
ingredientsRow(name, quantity, image)
{
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
flex: 2, // 20%
child: Container(
alignment: Alignment.center,
child: Image.network(image,
height: 45,
)
),
),
Expanded(
flex: 4, // 60%
child: Container(
child:Text(
name,
style: TextStyle(
color: Color(0xff41453c),
fontSize: 15,
fontWeight: FontWeight.w400
),
)
),
),
Expanded(
flex: 4, // 20%
child: Container(
alignment: Alignment.center,
child:Text(
quantity,
style: TextStyle(
color: Color(0xff41453c),
fontSize: 15,
fontWeight: FontWeight.w400
),
)
),
)
],
);
}
and here is my data model class
class RecipeModel{
final int id;
final String image;
final List<Ingredient> ingredients;
RecipeModel({this.id, this.image, this.ingredients});
factory RecipeModel.fromJson(Map<String, dynamic> parsedJson){
var list = parsedJson['ingredients'] as List;
print(list.runtimeType);
List<Ingredient> ingredientsList = list.map((i) => Ingredient.fromJson(i)).toList();
return RecipeModel(
id: parsedJson['id'],
image: parsedJson['image'],
ingredients: ingredientsList
);
}
}
class Ingredient {
final String name;
final String quantity;
final String image;
Ingredient({this.name, this.quantity, this.image});
factory Ingredient.fromJson(Map<String, dynamic> parsedJson){
return Ingredient(
name:parsedJson['name'],
quantity:parsedJson['quantity'],
image:parsedJson['image']
);
}
}
Best way to do this is using a FutureBuilder.
I've checked at your code and changed mainly 4 things:
1- I used an approach with FutureBuilder, which is built for that purpose.
2- Removed ingredientsList variable, and moved the code it to a function named _buildIngredientList with return type Widget.
3- Removed bool variable, because using FutureBuilder it is no longer needed.
4- Added the return type "Widget" to ingredientsRow function, because otherwise it would throw a type error.
Check out the code below:
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:stackoverflowsamples/models.dart';
void main() => runApp(
MaterialApp(home: HomePage(),
theme: ThemeData.fallback(),
),
);
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
var posts;
///3 - Remove bool
void initState() {
super.initState();
getRecipeById().then((value) => {
setState((){
posts = value;
})
});
}
Widget build(BuildContext context) {
return SafeArea(
top: true,
child: Scaffold(
body: Directionality(
textDirection: TextDirection.ltr,
child: SingleChildScrollView(
child:
FutureBuilder( ///1
future: getRecipeById(),
builder: (context, snapshot) {
if(snapshot.connectionState == ConnectionState.done) {
return Column(
children: <Widget>[
_buildIngredientList(),
],
);
} else {
return Container(
alignment: Alignment.center,
child: Text("loading now..")
);
}
}
),
),
),
)
);
}
Widget _buildIngredientList() { ///2
return Container(
width: MediaQuery.of(context).size.width,
padding: EdgeInsets.only(left: 1.0, right: 25.0),
margin: const EdgeInsets.only(bottom: 20.0),
child: Container(
child: Column(
children: posts.ingredients.map<Widget>((data) =>
ingredientsRow(data.name, data.quantity, data.image)
).toList(),
),
),
);
}
///4
Widget ingredientsRow(name, quantity, image) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
flex: 2, // 20%
child: Container(
alignment: Alignment.center,
child: Image.network(image,
height: 45,
)
),
),
Expanded(
flex: 4, // 60%
child: Container(
child:Text(
name,
style: TextStyle(
color: Color(0xff41453c),
fontSize: 15,
fontWeight: FontWeight.w400
),
)
),
),
Expanded(
flex: 4, // 20%
child: Container(
alignment: Alignment.center,
child:Text(
quantity,
style: TextStyle(
color: Color(0xff41453c),
fontSize: 15,
fontWeight: FontWeight.w400
),
)
),
)
],
);
}
getRecipeById() async {
///I've pasted the json as literal here because otherwise I couldn't make it run on my side.
var jsonResponse = jsonDecode('''{
"status": true,
"data": {
"id": 1,
"image": "https://img.taste.com.au/fruCLEZM/taste/2019/08/chicken-karahi-153167-2.jpg",
"calories": 100,
"ingredients_count": 5,
"serve": 1,
"views": 1,
"time": 1,
"translate": {
"post_title": "Chicken Karahi",
"post_description": "spicy and tasteful chicken karahi."
},
"ingredients": [
{
"name": "yogurt",
"quantity": "1 cup",
"image": "https://www.archanaskitchen.com/images/archanaskitchen/BasicRecipes_HOW_TO/How_To_Make_Fresh_Homemade_Yogurt_Curd_400.jpg"
},
{
"name": "red chilli",
"quantity": "100 gram",
"image": "https://ik.imagekit.io/91ubcvvnh3k/tr:w-500/https://www.planetorganic.com//images/products/medium/26148.jpg"
}
]
}
}''');
posts = RecipeModel.fromJson(jsonResponse['data']);
return posts;
}
}