The argument type 'int?' can't be assigned to the parameter type 'int' - class

this is RadioModel.dart
I am a beginner in flutter and I want to display my JSON file data on vx swipper.builder but i don't know whats going on here when i pass item count i face this error i know i am doing something wrong and i can't fix this
I am a beginner in flutter and I want to display my JSON file data on vx swipper.builder but i don't know whats going on here when i pass item count i face this error i know i am doing something wrong and i can't fix this
I am a beginner in flutter and I want to display my JSON file data on vx swipper.builder but i don't know whats going on here when i pass item count i face this error i know i am doing something wrong and i can't fix this
import 'dart:convert';
class MyRadioList {
static List<MyRadio>? radios;
// Get Item by ID
MyRadio getById(int id) =>
radios!.firstWhere((element) => element.id == id, orElse: null);
// Get Item by position
MyRadio getByPosition(int pos) => radios![pos];
}
class MyRadio {
final int id;
final int order;
final String name;
final String tagline;
final String color;
final String desc;
final String url;
final String category;
final String icon;
final String image;
final String lang;
MyRadio({
required this.id,
required this.order,
required this.name,
required this.tagline,
required this.color,
required this.desc,
required this.url,
required this.category,
required this.icon,
required this.image,
required this.lang,
});
factory MyRadio.fromMap(Map<String, dynamic> map) {
return MyRadio(
id: map['id'],
order: map['order'],
name: map['name'],
tagline: map['tagline'],
color: map['color'],
desc: map['desc'],
url: map['url'],
category: map['category'],
icon: map['icon'],
image: map['image'],
lang: map['lang'],
);
}
toMap() => {
"id": id,
"order": order,
"name": name,
"tagline": tagline,
"color": color,
"desc": desc,
"url": url,
"category": category,
"icon": icon,
"image": image,
"lang": lang,
};
}
// this is HomePage.dart
import 'dart:convert';
import 'dart:ffi';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_application_1/models/RadioModel.dart';
import 'package:flutter_application_1/utils/Ai_Utils.dart';
import 'package:velocity_x/velocity_x.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
//get daata from radio model
#override
void initstate() {
super.initState();
fetchradios();
}
fetchradios() async {
final radioJson = await rootBundle.loadString("assets/radio.json");
final decodedData = jsonDecode(radioJson);
MyRadioList.radios = List.from(decodedData)
.map<MyRadio>(((radio) => MyRadio.fromMap(radio)))
.toList();
setState(() {});
}
#override
Widget build(BuildContext context) {
return Scaffold(
drawer: Drawer(),
body: Stack(children: [
VxAnimatedBox()
.withGradient(LinearGradient(
colors: [AiColors.primaryColor1, AiColors.primaryColor2],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
))
.size(context.screenWidth, context.screenHeight)
.make(),
AppBar(
title: "AI Radio".text.xl4.bold.white.make().shimmer(
primaryColor: Vx.purple300, secondaryColor: Colors.white),
elevation: 0.0,
backgroundColor: Colors.transparent,
centerTitle: true,
).h(100.0).p16(),
VxSwiper.builder(
itemCount: MyRadioList.radios?.length, // error line
itemBuilder: (context, index) {
final rad = MyRadioList.radios![index];
return VxBox(child: ZStack([]))
.bgImage(DecorationImage(image: NetworkImage(rad.image)))
.make();
})
]),
);
}
}

itemCount must be a non-nullable int.
But your static List<MyRadio>? radios is a nullable List, so the length may be null if the List is never initialized
You can use the If-null operator ?? to initialize it to 0 or whatever default value you want to use if the length happens to be null
Change this line:
itemCount: MyRadioList.radios?.length, // error line
To this:
itemCount: MyRadioList.radios?.length ?? 0 // 0 or whatever default value
The line above essentially reads if MyRadioList.radios?.length is not null, then use it, otherwise set MyRadioList.radios?.length to 0.
Using ?? ensures that the length of your list will never be null

Related

Using GetX package with firebase and PageView.builder()

I'm trying to implement infinite scrolling in flutter using Getx and PageView.builder(). So far i've been able to get all the data from my firebase database to display the image, but i'm unable to implement the infinite pagination.
I want say 10 images to be displayed on first load (fetched from my firestore), and then as the user scrolls down to the 10th image, it should load the next 10 images from firestore.
Below is my code:
In my model i have a file name "image.dart" and it contains this:
import "package:cloud_firestore/cloud_firestore.dart";
class Images {
String username;
String uid;
String id;
List likes;
int commentCount;
int downloadCount;
String tag;
String description;
String imageUrl;
String profilePhoto;
bool verified;
Images({
required this.username,
required this.uid,
required this.id,
required this.likes,
required this.commentCount,
required this.downloadCount,
required this.tag,
required this.description,
required this.imageUrl,
required this.profilePhoto,
required this.verified,
});
Map<String, dynamic> toJson() => {
"username": username,
"uid": uid,
"id": id,
"likes": likes,
"commentCount": commentCount,
"downloadCount": downloadCount,
"tag": tag,
"description": description,
"imageUrl": imageUrl,
"profilePhoto": profilePhoto,
"verified": verified,
};
static Images fromSnap(DocumentSnapshot snap) {
var snapshot = snap.data() as Map<String, dynamic>;
return Images(
username: snapshot['username'],
uid: snapshot['uid'],
id: snapshot['id'],
likes: snapshot['likes'],
commentCount: snapshot['commentCount'],
downloadCount: snapshot['downloadCount'],
tag: snapshot['tag'],
description: snapshot['description'],
imageUrl: snapshot['imageUrl'],
profilePhoto: snapshot['profilePhoto'],
verified: snapshot['verified']);
}
}
#
Then in my controller folder i have this file called image_controller.dart and it contains this:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class ImageController extends GetxController {
var isDownloading = false.obs;
final Rx<List<Images>> _imageList = Rx<List<Images>>([]);
List<Images> get imageList => _imageList.value;
List<Map<String, dynamic>> list = [];
bool isMoreData = true;
DocumentSnapshot? lastDocument;
#override
void onInit() {
super.onInit();
_imageList.bindStream(
firestore.collection('images').snapshots().map((QuerySnapshot query) {
List<Images> retVal = [];
for (var element in query.docs) {
retVal.add(
Images.fromSnap(element),
);
}
return retVal;
}));
}
//................................code continues
Then in my view folder i have a file named image_screen.dart and it contains this:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class ImageScreen extends StatelessWidget {
ImageScreen({Key? key}) : super(key: key);
final ImageController imageController = Get.put(ImageController());
#override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Scaffold(
body: Obx(() {
return PageView.builder(
itemCount: imageController.imageList.length,
controller: PageController(initialPage: 0, viewportFraction: 1),
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
final data = imageController.imageList[index];
return Stack(
children: [
ImagePlayerItem(
imageUrl: data.imageUrl,
),
Column(
children: [
const SizedBox(
height: 100,
),
// .................code continues...................

How to link up web api call to the list view

So i have my dart call to my api get method. Btw the way am just learning flutter and dart and trying out basic crud operations I would use to be doing in .net and c#
import 'dart:convert';
import 'package:theapp/models/Players.dart';
import 'package:http/http.dart';
class ApiService {
final String apiUrl = "https://apiurlhidden.com/api";
final String getAllPlayersEndPoint = "/GetAllPlayers/";
Future<List<Player>> getAllPlayers() async {
final getallPlayersUrl = Uri.parse(apiUrl + getAllPlayersEndPoint);
Response res = await get(getallPlayersUrl);
if (res.statusCode == 200) {
List<dynamic> body = jsonDecode(res.body);
List<Player> players =
body.map((dynamic item) => Player.fromJson(item)).toList();
return players;
} else {
throw "Failed to load cases list";
}
}
}
And I have my listview here but it complaining saying key and players do not exist
import 'package:flutter/material.dart';
import 'package:theapp/models/Players.dart';
class PlayerList extends StatelessWidget {
List<Player> players = [];
PlayerList({Key key, this.players}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: players == null ? 0 : players.length,
itemBuilder: (BuildContext context, int index) {
return Card(
child: InkWell(
onTap: () {},
child: ListTile(
leading: Icon(Icons.person),
title: Text(players[index].firstName),
subtitle: Text(players[index].surname.toString()),
),
));
});
}
}
My Model
class Player {
final int id;
final int type;
final String playerLevel;
final String firstName;
final String surname;
Player(this.id, this.type, this.playerLevel, this.firstName, this.surname);
factory Player.fromJson(Map<String, dynamic> json) {
return Player(
json['id'],
json['type'],
json['playerlevel'],
json['firstname'],
json['surname'],
);
}
#override
String toString() =>
'Players{id: $id, firstName: $firstName, lastName: $surname}';
}
Is there any reason why it should not recognize players and key in my list view page also how do I get the items to appear in the listview.
Picture only added to show the context in the items I mentioned above. Also coming from a .net background I would normally use an observable collection so it gets any changes in data in real-time am I using the correct approach for that.
Use required keyword to make parameters mandatory.
PlayerList({required Key key, required this.players}) : super(key: key);
Named parameters are optional unless they’re explicitly marked as required.
See Parameters for details.

Flutter HTTP Post Request does not reach Node-RED on Raspberry Pi

I am trying to send data from Flutter to Node-RED (to Raspberry Pi) over HTTP (not HTTPS). The URL http://bierbrauserver.ddns.net is from NO-IP (DDNS). The transfer to a test server from a Youtube Tutorial works fine. But when I change the URL from "https://reqres.in/api/users" to "http://bierbrauserver.ddns.net:1880" I get no input in the debug window of Node-RED. I tried in the AndroidManifest.xml to add the entry
so that http is allowed, but that didn't solve the problem either.
Furthermore I checked the port forwarding in the WLAN router configuration of the network where the Raspberry Pi is located. Here a port forwarding of HTTP and 1880 (Node-RED) was configured. The connection of the IP addresses should be ok, because I can access a database from an external port, which is also located on the Raspberry Pi. Can it be that only httpS post requests are possible ?
Future<UserModel> createUser(String name, String jobTitle)async{
const String Url = "https://reqres.in/api/users";
// const String Url = "https://bierbrauserver.ddns.net:1880";
final response = await http.post(Uri.parse(Url),body:
{
"name": name,
"job": jobTitle
});
if (response.statusCode == 201) {
final String responseString = response.body;
return userModelFromJson(responseString);
}
else
{
print(response.statusCode);
return UserModel(name:'Fail',job: 'Fail', id: 'Fail', createdAt: DateTime.now());
}
}
Thank you for your help.
The problem is solved. The program code has already been modified because I forgot to answer the question immediately when the problem was fixed. The problem was hidden in the Node-RED program. The wrong Node was selected in Node-RED.
The URL was extended with "/test", which is reused in Node-RED in the "http in" node. Now everything works fine.
For your information: "Zutat_1", "Zutat_2", "Zutat_3" and "Zutat_4" are global variables in this program and therefore do not have to be passed to the "createRezept" function.
Additionally, it should be mentioned that some elements in the code that do not belong to the English language are executed in the German language.
Future<RezeptModel> createRezept()async{
const String Url = "http://bierbrauserver.ddns.net:1880/test";
final response = await http.post(Uri.parse(Url),body:
{
"zutat1": Zutat_1.toStringAsFixed(2),
"zutat2": Zutat_2.toStringAsFixed(2),
"zutat3": Zutat_3.toStringAsFixed(2),
"zutat4": Zutat_4.toStringAsFixed(2),
"createdAt" : DateTime.now().toIso8601String()
});
if (response.statusCode == 201) {
final String responseString = response.body;
return rezeptModelFromJson(responseString);
}
else
{
print(response.statusCode);
return RezeptModel(zutat1:"Fehler",zutat2: "Fehler", zutat3: "Fehler", zutat4: "Fehler",createdAt: DateTime.now());
}
}
Here is the code which is used for parsing.(This is in a separate file, which in my case is named "Rezept_model.dart" )
import 'dart:convert';
RezeptModel rezeptModelFromJson(String str) => RezeptModel.fromJson(json.decode(str));
String rezeptModelToJson(RezeptModel data) => json.encode(data.toJson());
class RezeptModel {
RezeptModel({
required this.zutat1,
required this.zutat2,
required this.zutat3,
required this.zutat4,
required this.createdAt,
});
String zutat1;
String zutat2;
String zutat3;
String zutat4;
DateTime createdAt;
factory RezeptModel.fromJson(Map<String, dynamic> json) => RezeptModel(
zutat1: json["zutat1"],
zutat2: json["zutat2"],
zutat3: json["zutat3"],
zutat4: json["zutat4"],
createdAt: DateTime.parse(json["createdAt"]),
);
Map<String, dynamic> toJson() => {
"zutat1": zutat1,
"zutat2": zutat2,
"zutat3": zutat3,
"zutat4": zutat4,
"createdAt": createdAt.toIso8601String(),
};
}
For completeness here is the whole code of the main program.
import 'dart:convert';
import 'dart:math';
import 'package:bier_brau_project/variables.dart';
import 'package:bier_brau_project/rezept_model.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Bier Brau App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'HTTP Test Site'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
Future<RezeptModel> createRezept()async{
const String Url = "http://bierbrauserver.ddns.net:1880/test";
final response = await http.post(Uri.parse(Url),body:
{
"zutat1": Zutat_1.toStringAsFixed(2),
"zutat2": Zutat_2.toStringAsFixed(2),
"zutat3": Zutat_3.toStringAsFixed(2),
"zutat4": Zutat_4.toStringAsFixed(2),
"createdAt" : DateTime.now().toIso8601String()
});
if (response.statusCode == 201) {
final String responseString = response.body;
return rezeptModelFromJson(responseString);
}
else
{
print(response.statusCode);
return RezeptModel(zutat1:"Fehler",zutat2: "Fehler", zutat3: "Fehler", zutat4: "Fehler",createdAt: DateTime.now());
}
}
class _MyHomePageState extends State<MyHomePage> {
RezeptModel _rezept = RezeptModel(zutat1: "init", zutat2: "init", zutat3: "init",zutat4: "init", createdAt: DateTime.now());
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
MySlider(Min:22.0,Max:40.0,Devisions: 100,unit:'l',title: 'Wasser',ID:1),
MySlider(Min:4.0,Max:20.0,Devisions: 100,unit:'kg',title:'Malz',ID: 2,),
MySlider(Min:60.0,Max:300.0,Devisions: 100,unit:'g',title:'Hopfen',ID: 3,),
MySlider(Min:12.0,Max:60.0,Devisions: 100,unit:'g',title:'Hefe',ID:4),
const SizedBox(height:32.0,),
Text( "Wasser "+ _rezept.zutat1 +"\n"
+"Malz "+_rezept.zutat2 +"\n"
+"Mopfen "+ _rezept.zutat3 +"\n"
+"Hefe "+ _rezept.zutat4 +"\n"
+"ist Erfolgreich übertragen worden "
+ _rezept.createdAt.toIso8601String())
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: ()async{
final RezeptModel rezept= await createRezept();
setState(() {
_rezept=rezept;
});
},
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
/// This is the stateful widget that the main application instantiates.
class MySlider extends StatefulWidget {
MySlider({Key? key,required this.Min, required this.Max,required this.Devisions,required this.unit,required this.title,required this.ID}): super(key: key);
final double Min;
final double Max;
final String unit;
final String title;
final int Devisions;
final int ID;
bool ValueChanged= false;
#override
State<MySlider> createState() => _MySliderState();
}
/// This is the private State class that goes with MyStatefulWidget.
class _MySliderState extends State<MySlider> {
double _currentSliderValue =0;
#override
Widget build(BuildContext context) {
return Padding (
padding: const EdgeInsetsDirectional.fromSTEB(32.0, 32.0, 32.0, 16.0),
child: Column(children: <Widget> [
Text(
widget.title,
style: const TextStyle(
color: Colors.black54,
height: 1,
fontSize: 18
),
),
Slider(
value: widget.ValueChanged== false ? ((widget.Max-widget.Min)/2)+widget.Min : _currentSliderValue,
min: widget.Min,
max: widget.Max,
divisions: widget.Devisions,
label: _currentSliderValue.toStringAsFixed(2),
onChanged: (double value) {
setState(() {
_currentSliderValue = value;
first_call = false;
widget.ValueChanged =true;
switch(widget.ID) {
case 1: {Zutat_1 =double.parse(value.toStringAsFixed(2));}
break;
case 2: {Zutat_2 =double.parse(value.toStringAsFixed(2));}
break;
case 3: {Zutat_3 =double.parse(value.toStringAsFixed(2));}
break;
case 4: {Zutat_4 =double.parse(value.toStringAsFixed(2));}
break;
default: {}
break;
}
});
},
),
Text(
(widget.ValueChanged== false ?((widget.Max-widget.Min)/2)+widget.Min : _currentSliderValue.toStringAsFixed(2)).toString() + ' '+widget.unit,
),
])
);
}
}
Many thanks to all those who have dealt with this problem.
Here are still two images deposited around the connections to clarify.
Node-RED program to receive from http post
Android Studio emulator with the test application
Change your code to this:
final response = await http.post(Uri.parse(Url),body:
{
"name": name,
"job": jobTitle
});
if (response.statusCode == 201) {
final responseString = jsonDecode(_res.body)
return userModelFromJson(responseString);
}
else
{
print(response.statusCode);
return UserModel(name:'Fail',job: 'Fail', id: 'Fail', createdAt: DateTime.now());
}
}

Flutter: How to get json nested Map method

New to Flutte/Dart. What could be causing my mapping issues?
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<List<Photo>> fetchPhotos(http.Client client) async {
final response =
await client.get('https://cloud.iexapis.com/stable/stock/market/batch?symbols=aapl,fb&types=quote&token=hidden');
// Use the compute function to run parsePhotos in a separate isolate.
return compute(parsePhotos, response.body);
}
// A function that converts a response body into a List<Photo>.
List<Photo> parsePhotos(String response) {
List<Photo> Photos = new List<Photo>();
List parsePhotos= json.decode(response.toString());
for (int i = 0; i < parsePhotos.length; i++) {
Photos.add(new Photo.fromJson(parsePhotos[i]));
}
return Photos;
}
class Photo {
final String symbol;
final String companyName;
final String primaryExchange;
final String calculationPrice;
final int open;
final int openTime;
final double close;
final int closeTime;
final double high;
final double low;
final double latestPrice;
final String latestSource;
final String latestTime;
final int latestUpdate;
final int latestVolume;
final dynamic iexRealtimePrice;
final dynamic iexRealtimeSize;
final dynamic iexLastUpdated;
final double delayedPrice;
final int delayedPriceTime;
final double extendedPrice;
final double extendedChange;
final double extendedChangePercent;
final int extendedPriceTime;
final double previousClose;
final int previousVolume;
final int change;
final double changePercent;
final int volume;
final dynamic iexMarketPercent;
final dynamic iexVolume;
final int avgTotalVolume;
final dynamic iexBidPrice;
final dynamic iexBidSize;
final dynamic iexAskPrice;
final dynamic iexAskSize;
final int marketCap;
final double peRatio;
final double week52High;
final int week52Low;
final double ytdChange;
final int lastTradeTime;
final bool isUsMarketOpen;
Photo({
this.symbol,
this.companyName,
this.primaryExchange,
this.calculationPrice,
this.open,
this.openTime,
this.close,
this.closeTime,
this.high,
this.low,
this.latestPrice,
this.latestSource,
this.latestTime,
this.latestUpdate,
this.latestVolume,
this.iexRealtimePrice,
this.iexRealtimeSize,
this.iexLastUpdated,
this.delayedPrice,
this.delayedPriceTime,
this.extendedPrice,
this.extendedChange,
this.extendedChangePercent,
this.extendedPriceTime,
this.previousClose,
this.previousVolume,
this.change,
this.changePercent,
this.volume,
this.iexMarketPercent,
this.iexVolume,
this.avgTotalVolume,
this.iexBidPrice,
this.iexBidSize,
this.iexAskPrice,
this.iexAskSize,
this.marketCap,
this.peRatio,
this.week52High,
this.week52Low,
this.ytdChange,
this.lastTradeTime,
this.isUsMarketOpen,
});
factory Photo.fromJson(String str) => Photo.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory Photo.fromMap(Map<String, dynamic> json) => Photo(
symbol: json["symbol"],
companyName: json["companyName"],
primaryExchange: json["primaryExchange"],
calculationPrice: json["calculationPrice"],
open: json["open"],
openTime: json["openTime"],
close: json["close"].toDouble(),
closeTime: json["closeTime"],
high: json["high"].toDouble(),
low: json["low"].toDouble(),
latestPrice: json["latestPrice"].toDouble(),
latestSource: json["latestSource"],
latestTime: json["latestTime"],
latestUpdate: json["latestUpdate"],
latestVolume: json["latestVolume"],
iexRealtimePrice: json["iexRealtimePrice"],
iexRealtimeSize: json["iexRealtimeSize"],
iexLastUpdated: json["iexLastUpdated"],
delayedPrice: json["delayedPrice"].toDouble(),
delayedPriceTime: json["delayedPriceTime"],
extendedPrice: json["extendedPrice"].toDouble(),
extendedChange: json["extendedChange"].toDouble(),
extendedChangePercent: json["extendedChangePercent"].toDouble(),
extendedPriceTime: json["extendedPriceTime"],
previousClose: json["previousClose"].toDouble(),
previousVolume: json["previousVolume"],
change: json["change"],
changePercent: json["changePercent"].toDouble(),
volume: json["volume"],
iexMarketPercent: json["iexMarketPercent"],
iexVolume: json["iexVolume"],
avgTotalVolume: json["avgTotalVolume"],
iexBidPrice: json["iexBidPrice"],
iexBidSize: json["iexBidSize"],
iexAskPrice: json["iexAskPrice"],
iexAskSize: json["iexAskSize"],
marketCap: json["marketCap"],
peRatio: json["peRatio"].toDouble(),
week52High: json["week52High"].toDouble(),
week52Low: json["week52Low"],
ytdChange: json["ytdChange"].toDouble(),
lastTradeTime: json["lastTradeTime"],
isUsMarketOpen: json["isUSMarketOpen"],
);
Map<String, dynamic> toMap() => {
"symbol": symbol,
"companyName": companyName,
"primaryExchange": primaryExchange,
"calculationPrice": calculationPrice,
"open": open,
"openTime": openTime,
"close": close,
"closeTime": closeTime,
"high": high,
"low": low,
"latestPrice": latestPrice,
"latestSource": latestSource,
"latestTime": latestTime,
"latestUpdate": latestUpdate,
"latestVolume": latestVolume,
"iexRealtimePrice": iexRealtimePrice,
"iexRealtimeSize": iexRealtimeSize,
"iexLastUpdated": iexLastUpdated,
"delayedPrice": delayedPrice,
"delayedPriceTime": delayedPriceTime,
"extendedPrice": extendedPrice,
"extendedChange": extendedChange,
"extendedChangePercent": extendedChangePercent,
"extendedPriceTime": extendedPriceTime,
"previousClose": previousClose,
"previousVolume": previousVolume,
"change": change,
"changePercent": changePercent,
"volume": volume,
"iexMarketPercent": iexMarketPercent,
"iexVolume": iexVolume,
"avgTotalVolume": avgTotalVolume,
"iexBidPrice": iexBidPrice,
"iexBidSize": iexBidSize,
"iexAskPrice": iexAskPrice,
"iexAskSize": iexAskSize,
"marketCap": marketCap,
"peRatio": peRatio,
"week52High": week52High,
"week52Low": week52Low,
"ytdChange": ytdChange,
"lastTradeTime": lastTradeTime,
"isUSMarketOpen": isUsMarketOpen,
};
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final appTitle = 'Isolate Demo';
return MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
MyHomePage({Key key, this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: FutureBuilder<List<Photo>>(
future: fetchPhotos(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? PhotosList(photos: snapshot.data)
: Center(child: CircularProgressIndicator());
},
),
);
}
}
class PhotosList extends StatelessWidget {
final List<Photo> photos;
// final parsePhotos = json.decode(response.body).cast<Map<String, dynamic>>();
PhotosList({Key key, this.photos}) : super(key: key);
#override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: photos.length,
itemBuilder: (context, index) {
return Image.network(photos[index].companyName);
},
);
}
}
Error
Launching lib\main.dart on Android SDK built for x86 in debug mode...
Initializing gradle...
Resolving dependencies...
Running Gradle task 'assembleDebug'...
Built build\app\outputs\apk\debug\app-debug.apk.
Flutter is taking longer than expected to report its views. Still trying...
I/OpenGLRenderer( 5371): Initialized EGL, version 1.4
D/OpenGLRenderer( 5371): Swap behavior 1
D/ ( 5371): HostConnection::get() New Host Connection established 0xdd5d9200, tid 5399
D/EGL_emulation( 5371): eglCreateContext: 0xde80f4c0: maj 2 min 0 rcv 2
D/EGL_emulation( 5371): eglMakeCurrent: 0xde80f4c0: ver 2 0 (tinfo 0xde37faf0)
D/ ( 5371): HostConnection::get() New Host Connection established 0xc8bb7680, tid 5390
D/EGL_emulation( 5371): eglCreateContext: 0xde37cc00: maj 2 min 0 rcv 2
D/EGL_emulation( 5371): eglMakeCurrent: 0xde37cc00: ver 2 0 (tinfo 0xde37f810)
I/Choreographer( 5371): Skipped 411 frames! The application may be doing too much work on its main thread.
D/EGL_emulation( 5371): eglMakeCurrent: 0xde80f4c0: ver 2 0 (tinfo 0xde37faf0)
Syncing files to device Android SDK built for x86...
I/OpenGLRenderer( 5371): Davey! duration=8078ms; Flags=1, IntendedVsync=1110681936778, Vsync=1117531936504, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=1117546732479, AnimationStart=1117546825482, PerformTraversalsStart=1117546831170, DrawStart=1117600733845, SyncQueued=1117602574377, SyncStart=1117645210311, IssueDrawCommandsStart=1117645436189, SwapBuffers=1118338480166, FrameCompleted=1118803458523, DequeueBufferDuration=29600000, QueueBufferDuration=176000,
D/EGL_emulation( 5371): eglMakeCurrent: 0xde37cc00: ver 2 0 (tinfo 0xde37f810)
I/flutter ( 5371): Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List<dynamic>'
Json results:
{"AAPL":{"stats":{"week52change":0.232986,"week52high":255.93,"week52low":142,"marketcap":1136677331400,"employees":137000,"day200MovingAvg":199.29,"day50MovingAvg":225.28,"float":4436680630.59,"avg10Volume":26482506.4,"avg30Volume":26817874.5,"ttmEPS":11.9342,"ttmDividendRate":3,"companyName":"Apple, Inc.","sharesOutstanding":4443270000,"maxChangePercent":252.2871,"year5ChangePercent":1.3384,"year2ChangePercent":0.5329,"year1ChangePercent":0.1512,"ytdChangePercent":0.6199,"month6ChangePercent":0.2152,"month3ChangePercent":0.2274,"month1ChangePercent":0.1391,"day30ChangePercent":0.1696,"day5ChangePercent":0.0272,"nextDividendDate":"2019-11-07","dividendYield":0.011726995543741695,"nextEarningsDate":"2020-02-04","exDividendDate":"2019-11-07","peRatio":21.44,"beta":1.534927573962706},"quote":{"symbol":"AAPL","companyName":"Apple, Inc.","primaryExchange":"NASDAQ","calculationPrice":"close","open":249.5,"openTime":1572615000544,"close":255.82,"closeTime":1572638400572,"high":255.93,"low":249.16,"latestPrice":255.82,"latestSource":"Close","latestTime":"November 1, 2019","latestUpdate":1572638400572,"latestVolume":38139225,"iexRealtimePrice":null,
Json Screenshot
[
Stack Trace
{"AAPL":{"stats":{"week52change":0.232986,"week52high":255.93,"week52low":142,"marketcap":1136677331400,"employees":137000,"day200MovingAvg":199.29,"day50MovingAvg":225.28,"float":4436680630.59,"avg10Volume":26482506.4,"avg30Volume":26817874.5,"ttmEPS":11.9342,"ttmDividendRate":3,"companyName":"Apple, Inc.","sharesOutstanding":4443270000,"maxChangePercent":252.2871,"year5ChangePercent":1.3384,"year2ChangePercent":0.5329,"year1ChangePercent":0.1512,"ytdChangePercent":0.6199,"month6ChangePercent":0.2152,"month3ChangePercent":0.2274,"month1ChangePercent":0.1391,"day30ChangePercent":0.1696,"day5ChangePercent":0.0272,"nextDividendDate":"2019-11-07","dividendYield":0.011726995543741695,"nextEarningsDate":"2020-02-04","exDividendDate":"2019-11-07","peRatio":21.44,"beta":1.534927573962706},"quote":{"symbol":"AAPL","companyName":"Apple, Inc.","primaryExchange":"NASDAQ","calculationPrice":"close","open":249.5,"openTime":1572615000544,"close":255.82,"closeTime":1572638400572,"high":255.93,"low":249.16,"latestPrice":255.82,"latestSource":"Close","latestTime":"November 1, 2019","latestUpdate":1572638400572,"latestVolume":38139225,"iexRealtimePrice":null,
Screenshot
Expected:
Example: https://flutter.dev/docs/cookbook/networking/background-parsing
Root of JSON that you attached as "Json results" is map, but you're trying to assign it to List variable here:
List parsePhotos= json.decode(response.toString());
Make sure you're working right with your response structure. Also access body of the response, don't convert whole response object to string:
Map parsedResponse = json.decode(response.body);
Also I highly recommend using code generators for JSON (de)serialization to make it easier for you. json_serializable and build_runner will help you do that. I'll show you an example how to deserialize an object with nested maps:
{"d":0.5,"nestedMaps":{"test":{"s":"a"},"test2":{"s":"a"}},"list":["a","b"]}
Define class for it and use JsonSerializable annotation:
import 'package:json_annotation/json_annotation.dart';
part 'photo.g.dart';
#JsonSerializable()
class Photo {
final double d;
final Map<String, Map> nestedMaps;
final List<String> list;
Photo(this.d, this.nestedMaps, this.list);
factory Photo.fromJson(Map<String, dynamic> json) => _$PhotoFromJson(json);
Map<String, dynamic> toJson() => _$PhotoToJson(this);
}
You can specify dynamic type as well. Now run code generator:
flutter packages pub run build_runner build
And now you can parse JSON:
Photo.fromJson(jsonDecode('{"d":0.5,"nestedMaps":{"test":{"s":"a"},"test2":{"s":"a"}},"list":["a","b"]}'));
Dart can only decode/encode Map with String keys, so be careful.
Full working demo tested with real token, you can copy paste run full code below
In example code, I have remove token, you have to added it back
json string in real response is "quote" and in your question is "stat"
You have to check response string before layout
Currently use quote is photos[index].data["quote"]["iexRealtimePrice"]
Real json string response from URL
{"AAPL":{"quote":{"symbol":"AAPL","companyName":"Apple, Inc.","primaryExchange":"NASDAQ","calculationPrice":"close","open":265.69,"openTime":1574260200209,"close":263.19,"closeTime":1574283600212,"high":266.083,"low":260.4,"latestPrice":263.19,"latestSource":"Close","latestTime":"November 20, 2019","latestUpdate":1574283600212,"latestVolume":26015446,"iexRealtimePrice":262.83,"iexRealtimeSize":19,"iexLastUpdated":1574283604924,"delayedPrice":263.19,"delayedPriceTime":1574283600212,"extendedPrice":263.35,"extendedChange":0.16,"extendedChangePercent":0.00061,"extendedPriceTime":1574384397682,"previousClose":266.29,"previousVolume":19069597,"change":-3.1,"changePercent":-0.01164,"volume":26015446,"iexMarketPercent":0.015005278018297284,"iexVolume":390369,"avgTotalVolume":24440833,"iexBidPrice":0,"iexBidSize":0,"iexAskPrice":0,"iexAskSize":0,"marketCap":1169424231300,"peRatio":22.05,"week52High":268,"week52Low":142,"ytdChange":0.674594,"lastTradeTime":1574283604924,"isUSMarketOpen":false}},"FB":{"quote":{"symbol":"FB","companyName":"Facebook, Inc.","primaryExchange":"NASDAQ","calculationPrice":"close","open":198.58,"openTime":1574260200212,"close":197.51,"closeTime":1574283600333,"high":199.59,"low":195.43,"latestPrice":197.51,"latestSource":"Close","latestTime":"November 20, 2019","latestUpdate":1574283600333,"latestVolume":11999607,"iexRealtimePrice":197.5,"iexRealtimeSize":100,"iexLastUpdated":1574283599989,"delayedPrice":197.5,"delayedPriceTime":1574283599989,"extendedPrice":196.5,"extendedChange":-1.01,"extendedChangePercent":-0.00511,"extendedPriceTime":1574384390404,"previousClose":199.32,"previousVolume":19070291,"change":-1.81,"changePercent":-0.00908,"volume":11999607,"iexMarketPercent":0.020256580069663948,"iexVolume":243071,"avgTotalVolume":14362105,"iexBidPrice":0,"iexBidSize":0,"iexAskPrice":0,"iexAskSize":0,"marketCap":563391349700,"peRatio":31.36,"week52High":208.66,"week52Low":123.02,"ytdChange":0.459965,"lastTradeTime":1574283599989,"isUSMarketOpen":false}}}
full code remove your token
import 'dart:async';
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
Future<List<Photo>> fetchPhotos(http.Client client) async {
final response =
await client.get('https://cloud.iexapis.com/stable/stock/market/batch?symbols=aapl,fb&types=quote&token=xxx');
/*String response = '''
{"AAPL":
{"stats":{"week52change":0.232986,"week52high":255.93,"week52low":142,"marketcap":1136677331400,"employees":137000,"day200MovingAvg":199.29,"day50MovingAvg":225.28,"float":4436680630.59,"avg10Volume":26482506.4,"avg30Volume":26817874.5,"ttmEPS":11.9342,"ttmDividendRate":3,"companyName":"Apple, Inc."
}
},
"FB":
{"stats":{"week52change":0.1,"week52high":255.93,"week52low":142,"marketcap":1136677331400,"employees":137000,"day200MovingAvg":199.29,"day50MovingAvg":225.28,"float":4436680630.59,"avg10Volume":26482506.4,"avg30Volume":26817874.5,"ttmEPS":11.9342,"ttmDividendRate":3,"companyName":"Apple, Inc."
}
}
}
''';*/
// Use the compute function to run parsePhotos in a separate isolate.
return compute(parsePhotos, response.body);
}
// A function that converts a response body into a List<Photo>.
List<Photo> parsePhotos(String responseBody) {
//final parsed = json.decode(responseBody).cast<Map<String, dynamic>>();
//return parsed.map<Photo>((json) => Photo.fromJson(json)).toList();
dynamic Obj = json.decode(responseBody);
print(Obj.length);
List<Photo> photoList = [];
Obj.forEach((k, v) => photoList.add(Photo(k, v)));
return photoList;
}
class Photo {
String symbol;
dynamic data;
Photo(this.symbol, this.data);
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
final appTitle = 'Isolate Demo';
return MaterialApp(
title: appTitle,
home: MyHomePage(title: appTitle),
);
}
}
class MyHomePage extends StatelessWidget {
final String title;
MyHomePage({Key key, this.title}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: FutureBuilder<List<Photo>>(
future: fetchPhotos(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) print(snapshot.error);
return snapshot.hasData
? PhotosList(photos: snapshot.data)
: Center(child: CircularProgressIndicator());
},
),
);
}
}
class PhotosList extends StatelessWidget {
final List<Photo> photos;
PhotosList({Key key, this.photos}) : super(key: key);
#override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: photos.length,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.album),
title: Text(photos[index].symbol),
subtitle: Text( ' ${photos[index].data["quote"]["iexRealtimePrice"]}'),
);
},
);
}
}
demo
Try this:
List<Photo> parsePhotos(String response) {
return List<Photo>.from(
json.decode(response.body).map((x) => Photo.fromJson(x)));
}
By the way, jsontodart is really helpful to convert json to object or object to json
Assuming the JSON structure you're downloading is fixed, you can specify the "path" to each property in Photo.fromJson as follows:
close: json["AAPL"]["quote"]["close"],
instead of:
close: json["close"],
Please run the following sample code and you'll see that Photo.close and Photo.latestVolume are now correcly loaded from your JSON because I have specified the correct "path" in Photo.fromJson:
import 'dart:convert';
void main() {
var jsonStream = '{"AAPL":{"stats":{"companyName":"Apple, Inc.","sharesOutstanding":4443270000,"maxChangePercent":252.2871,"year5ChangePercent":1.3384,"year2ChangePercent":0.5329,"beta":1.534927573962706},"quote":{"symbol":"AAPL","companyName":"Apple, Inc.","primaryExchange":"NASDAQ","calculationPrice":"close","open":249.5,"openTime":1572615000544,"close":255.82,"closeTime":1572638400572,"high":255.93,"low":249.16,"latestPrice":255.82,"latestSource":"Close","latestTime":"November 1, 2019","latestUpdate":1572638400572,"latestVolume":38139225,"iexRealtimePrice":null}}}';
var j = json.decode(jsonStream);
print(j);
print("");
print("Latest Volume: ${j["AAPL"]["quote"]["latestVolume"]}");
print("Close: ${j["AAPL"]["quote"]["close"]}");
print("");
var p = Photo.fromJson(j);
print("Latest Volume: ${p.latestVolume}");
print("Close: ${p.close}");
}
class Photo {
final String symbol;
final String companyName;
final String primaryExchange;
final String calculationPrice;
final int open;
final int openTime;
final double close;
final int closeTime;
final double high;
final double low;
final double latestPrice;
final String latestSource;
final String latestTime;
final int latestUpdate;
final int latestVolume;
final dynamic iexRealtimePrice;
final dynamic iexRealtimeSize;
final dynamic iexLastUpdated;
final double delayedPrice;
final int delayedPriceTime;
final double extendedPrice;
final double extendedChange;
final double extendedChangePercent;
final int extendedPriceTime;
final double previousClose;
final int previousVolume;
final int change;
final double changePercent;
final int volume;
final dynamic iexMarketPercent;
final dynamic iexVolume;
final int avgTotalVolume;
final dynamic iexBidPrice;
final dynamic iexBidSize;
final dynamic iexAskPrice;
final dynamic iexAskSize;
final int marketCap;
final double peRatio;
final double week52High;
final int week52Low;
final double ytdChange;
final int lastTradeTime;
final bool isUsMarketOpen;
Photo({
this.symbol,
this.companyName,
this.primaryExchange,
this.calculationPrice,
this.open,
this.openTime,
this.close,
this.closeTime,
this.high,
this.low,
this.latestPrice,
this.latestSource,
this.latestTime,
this.latestUpdate,
this.latestVolume,
this.iexRealtimePrice,
this.iexRealtimeSize,
this.iexLastUpdated,
this.delayedPrice,
this.delayedPriceTime,
this.extendedPrice,
this.extendedChange,
this.extendedChangePercent,
this.extendedPriceTime,
this.previousClose,
this.previousVolume,
this.change,
this.changePercent,
this.volume,
this.iexMarketPercent,
this.iexVolume,
this.avgTotalVolume,
this.iexBidPrice,
this.iexBidSize,
this.iexAskPrice,
this.iexAskSize,
this.marketCap,
this.peRatio,
this.week52High,
this.week52Low,
this.ytdChange,
this.lastTradeTime,
this.isUsMarketOpen,
});
factory Photo.fromJson(Map<String, dynamic> json) => Photo(
symbol: json["symbol"],
companyName: json["companyName"],
primaryExchange: json["primaryExchange"],
calculationPrice: json["calculationPrice"],
open: json["open"],
openTime: json["openTime"],
close: json["AAPL"]["quote"]["close"] as double, // Points to correct "path"
closeTime: json["closeTime"],
high: json["high"] as double,
low: json["low"] as double,
latestPrice: json["latestPrice"] as double,
latestSource: json["latestSource"],
latestTime: json["latestTime"],
latestUpdate: json["latestUpdate"],
latestVolume: json["AAPL"]["quote"]["latestVolume"], // Points to correct "path"
iexRealtimePrice: json["iexRealtimePrice"],
iexRealtimeSize: json["iexRealtimeSize"],
iexLastUpdated: json["iexLastUpdated"],
delayedPrice: json["delayedPrice"] as double,
delayedPriceTime: json["delayedPriceTime"],
extendedPrice: json["extendedPrice"] as double,
extendedChange: json["extendedChange"] as double,
extendedChangePercent: json["extendedChangePercent"] as double,
extendedPriceTime: json["extendedPriceTime"],
previousClose: json["previousClose"] as double,
previousVolume: json["previousVolume"],
change: json["change"],
changePercent: json["changePercent"] as double,
volume: json["volume"],
iexMarketPercent: json["iexMarketPercent"],
iexVolume: json["iexVolume"],
avgTotalVolume: json["avgTotalVolume"],
iexBidPrice: json["iexBidPrice"],
iexBidSize: json["iexBidSize"],
iexAskPrice: json["iexAskPrice"],
iexAskSize: json["iexAskSize"],
marketCap: json["marketCap"],
peRatio: json["peRatio"] as double,
week52High: json["week52High"] as double,
week52Low: json["week52Low"],
ytdChange: json["ytdChange"] as double,
lastTradeTime: json["lastTradeTime"],
isUsMarketOpen: json["isUSMarketOpen"],
);
}
You can run the code in DartPad at: https://dartpad.dartlang.org
One more thing: please note that I have changed your original code:
prop: json["prop"].toDouble(),
to:
propr: json["prop"] as double,
This is because .ToDouble() would fail if the JSON field is null. Unless you have a particular reason to require dynamic fields, you can declare them directly as double
Hope this helps :)

Flutter - how to read list from Firebase realtime database using model

[ Sorry for my bad English ]
In this project I'm viewing events lists in some pages from JSON API and in
CloudEvents page I'm viewing another list from Firebase Database, using Event model ...
Now when I run CloudEvents page I get null for itemsEvent[i].startDate
with this Error: A non-null String must be provided to a Text widget.
Open: Error Snapshot
Open: Firebase Database Snapshot
I used this Method for my model
This is my Event model
class Event {
String key;
String sectionID;
String sectionTitle;
String title;
String startDate;
String endDate;
String startDateAr;
String endDateAr;
String city;
String detail;
String location;
String more;
String link;
// for generalevent.json
String eventDate;
String eventDateAr;
Event(
{this.sectionID,
this.sectionTitle,
this.title,
this.startDate,
this.endDate,
this.startDateAr,
this.endDateAr,
this.city,
this.detail,
this.location,
this.more,
this.link,
this.eventDate,
this.eventDateAr});
factory Event.fromJson(Map<String, dynamic> json) {
return Event(
sectionID: json['section-id'],
sectionTitle: json['section-title'],
title: json['title'],
startDate: json['start-event-date'],
endDate: json['end-event-date'],
startDateAr: json['start-event-date-ar'],
endDateAr: json['end-event-date-ar'],
city: json['city'],
detail: json['detail'],
location: json['location'],
more: json['more'],
link: json['link'],
// for generalevent.json
eventDate: json['event-date'],
eventDateAr: json['event-date-ar'],
);
}
Event.fromSnapshot(DataSnapshot snapshot)
: key = snapshot.key,
title = snapshot.value['title'],
startDate = snapshot.value['startDate'];
toJson() {
return {
"title": title,
"startDate": startDate,
};
}
}
And this is my CloudEvents page
import 'package:events/UI/styleguide.dart';
import 'package:events/models/event.dart' as e;
import 'package:events/pages/account.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_database/ui/firebase_animated_list.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:intl/intl.dart' as intl;
final FirebaseAuth mAuth = FirebaseAuth.instance;
final db = FirebaseDatabase.instance.reference();
FirebaseUser mCurrentUser;
List<e.Event> itemsEvent = List();
e.Event itemEvent;
DatabaseReference dbEvent;
class CloudEvents extends StatefulWidget {
final GlobalKey<ScaffoldState> scaffoldKey;
const CloudEvents({Key key, #required this.scaffoldKey}) : super(key: key);
#override
_CloudEventsState createState() => _CloudEventsState();
}
class _CloudEventsState extends State<CloudEvents> {
ScrollController _hideButtonController;
var _isVisible;
#override
initState() {
super.initState();
...
itemEvent = e.Event();
final FirebaseDatabase database = FirebaseDatabase.instance;
dbEvent = database.reference().child('events');
dbEvent.onChildAdded.listen(_onEntryAddedEvent);
dbEvent.onChildChanged.listen(_onEntryChangedEvent);
...
}
_onEntryAddedEvent(Event event) {
setState(() {
itemsEvent.add(e.Event.fromSnapshot(event.snapshot));
});
}
_onEntryChangedEvent(Event event) {
var old = itemsEvent.singleWhere((entry) {
return entry.key == event.snapshot.key;
});
setState(() {
itemsEvent[e.Event.indexOf(old)] = e.Event.fromSnapshot(event.snapshot);
});
}
#override
Widget build(BuildContext context) {
return showEvents();
}
Widget showEvents(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height,
child: Stack(
children: <Widget>[
FirebaseAnimatedList(
query: dbEvent.child(mCurrentUser.uid),
itemBuilder: (_, DataSnapshot snapshot,
Animation<double> animation, int i) {
return new ListTile(
title: new Text(snapshot.value['title']), //snapshot works well
subtitle: new Text(itemsEvent[i].startDate), // this returns null
);
}),
...
],
),
);
}
...
}
I just realized the problem here, according to u/Cholojuanito's comment on reddit
I did his number 1 possible solution, and then I edited:
Text(itemsEvent[i].startDate) to
Text(e.Event.fromSnapshot(snapshot).startDate)
and it worked so well, thank you for everyone who commented on reddit.