Get data from JSON and add into the List on initState() - dart

I have JSON file below.
Data.json
[{
"rownum": 1,
"total": 10.99793271,
"total2": 106.65666751,
}, {
"rownum": 2,
"total": 10.99793271,
"total2": 106.65666751,
}]
and the class Item and List
List <Item> item;
class Item {
String row;
String total;
String total2;
Student({this.row, this.total, this.total2});
}
How can I get data from data.json and add them into List <Item> item on the initState()?
Like this
class MyAppState extends State<MyApp> {
#override
void initState() {
Future<String> _loadAStudentAsset() async {
return await rootBundle.loadString('assets/data.json');
}
//....some code to add value into list
super.initState();
}

That solution is also valid for you:
Flutter: How to display a short text file from assets on screen of phone?
If we make another example with same template:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
void main() {
runApp(Test());
}
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
Future _future;
Future<String> loadString() async =>
await rootBundle.loadString('assets/data.json');
#override
void initState() {
_future = loadString();
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: FutureBuilder(
future: _future,
builder: (context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return Text('Loading...');
}
List<dynamic> parsedJson = jsonDecode(snapshot.data);
items = parsedJson.map((element) {
return Item(
row: element['rownum'].toString(),
total: element['total'].toString(),
total2: element['total2'].toString(),
);
}).toList();
;
return ListView.builder(
itemCount: items.length,
itemBuilder: (context, index) {
final item = items[index];
return Column(
children: <Widget>[
Text(item.row),
Text(item.total),
Text(item.total2),
],
);
},
);
},
),
),
);
}
}
List<Item> items;
class Item {
String row;
String total;
String total2;
Item({this.row, this.total, this.total2});
}

class Item {
static final String db_row = "rownum";
static final String db_total = "total";
static final String db_total2 = "total2";
int row;
double total;
double total2;
Item({this.row, this.total, this.total2});
Item.fromMap(Map map) {
this.row = map[Item.db_row];
this.total = map[Item.db_total];
this.total2 = map[Item.db_total2];
}
Map toMap() =>
{Item.db_row: row, Item.db_total: total, Item.db_total2: total2};
static List<Item> fromMapList(mapList) {
List<Item> items = new List();
new List.from(mapList).forEach((mapItem) {
items.add(Item.fromMap(mapItem));
});
return items;
}
}
And
List <Item> items = Item.fromMapList(await rootBundle.loadString('assets/data.json'));

Related

The getter 'pokemon' was called on null. Receiver: null Tried calling: pokemon

I am trying to make a pokemon app. But I get this error:
"The getter 'pokemon' was called on null.
Receiver: null
Tried calling: pokemon"
I am putting error page to here.
I am using this API url for data "https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json"
And my Pokemon class is here:**
class Pokedex {
List<Pokemon> pokemon;
Pokedex({
this.pokemon});
Pokedex.fromJson(dynamic json) {
if (json["pokemon"] != null) {
pokemon = [];
json["pokemon"].forEach((v) {
pokemon.add(Pokemon.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
if (pokemon != null) {
map["pokemon"] = pokemon.map((v) => v.toJson()).toList();
}
return map;
}
}
class Pokemon {
int id;
String num;
String name;
String img;
List<String> type;
String height;
String weight;
String candy;
int candyCount;
String egg;
double spawnChance;
int avgSpawns;
String spawnTime;
List<double> multipliers;
List<String> weaknesses;
List<Next_evolution> nextEvolution;
Pokemon({
this.id,
this.num,
this.name,
this.img,
this.type,
this.height,
this.weight,
this.candy,
this.candyCount,
this.egg,
this.spawnChance,
this.avgSpawns,
this.spawnTime,
this.multipliers,
this.weaknesses,
this.nextEvolution});
Pokemon.fromJson(dynamic json) {
id = json["id"];
num = json["num"];
name = json["name"];
img = json["img"];
type = json["type"] != null ? json["type"].cast<String>() : [];
height = json["height"];
weight = json["weight"];
candy = json["candy"];
candyCount = json["candy_count"];
egg = json["egg"];
spawnChance = json["spawn_chance"];
avgSpawns = json["avg_spawns"];
spawnTime = json["spawn_time"];
multipliers = json["multipliers"] != null ? json["multipliers"].cast<double>() : [];
weaknesses = json["weaknesses"] != null ? json["weaknesses"].cast<String>() : [];
if (json["next_evolution"] != null) {
nextEvolution = [];
json["next_evolution"].forEach((v) {
nextEvolution.add(Next_evolution.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
map["id"] = id;
map["num"] = num;
map["name"] = name;
map["img"] = img;
map["type"] = type;
map["height"] = height;
map["weight"] = weight;
map["candy"] = candy;
map["candy_count"] = candyCount;
map["egg"] = egg;
map["spawn_chance"] = spawnChance;
map["avg_spawns"] = avgSpawns;
map["spawn_time"] = spawnTime;
map["multipliers"] = multipliers;
map["weaknesses"] = weaknesses;
if (nextEvolution != null) {
map["next_evolution"] = nextEvolution.map((v) => v.toJson()).toList();
}
return map;
}
}
class Next_evolution {
String num;
String name;
Next_evolution({
this.num,
this.name});
Next_evolution.fromJson(dynamic json) {
num = json["num"];
name = json["name"];
}
Map<String, dynamic> toJson() {
var map = <String, dynamic>{};
map["num"] = num;
map["name"] = name;
return map;
}
}
And this is my main.dart file:
import 'package:flutter/material.dart';
import 'package:pokemon_api/pokemon_list.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: PokemonList(),
);
}
}
And this is my pokemon_list.dart file:
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'model/pokedex.dart';
class PokemonList extends StatefulWidget {
const PokemonList({Key key}) : super(key: key);
#override
_PokemonListState createState() => _PokemonListState();
}
class _PokemonListState extends State<PokemonList> {
String url =
"https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json";
Pokedex pokedex;
var response;
Future<Pokedex> PokemonlariGetir() async {
response= await http.get(Uri.parse(url)).then((value){
var decodedJson = json.decode(response.body);
pokedex = Pokedex.fromJson(decodedJson);
});
debugPrint(pokedex.toString());
return pokedex;
}
#override
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Pokemon"),
),
body: FutureBuilder(
future: PokemonlariGetir(),
builder: (context, AsyncSnapshot<Pokedex> gelenPokedex) {
if (gelenPokedex.connectionState == ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else if (gelenPokedex.connectionState==ConnectionState.done) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemBuilder: (context,index){
return Text(gelenPokedex.data.pokemon[index].name);
});
// return GridView.count(crossAxisCount: 2,children:gelenPokedex.data.pokemon.map((poke){
// return Text(poke.name);
// }).toList(),);
}else{
return Center(child: CircularProgressIndicator(),);
}
}),
);
}
}

Flutter don't update UI from iOS using setState() method

I am invoking a method from native Swift code by using the platform channel like this:
channel.invokeMethod(METHOD_NAME, arguments: STRING_ARGUMENT)
in my Flutter class I handle the respective method call by using a callback
platform.setMethodCallHandler(_receiveFromHost);
The setMethodCallHandler() requires the callback to return a Future and I set state in _receiveFromHost method in Dart.
Problem is that my UI is not updated when Swift invokes the callback. Why?
call.method catch method string, state is set, but UI don't update.
video
This is my code in Swift:
let flutterEngine = (UIApplication.shared.delegate as! AppDelegate).flutterEngine
let flutterViewController = FlutterViewController(engine: flutterEngine!, nibName: nil, bundle: nil)
let channel = FlutterMethodChannel(name: "flutter_apple_pay", binaryMessenger: flutterViewController.binaryMessenger)
channel.invokeMethod("sendDidFinishAdding", arguments: "payment success")
And this is my code in Flutter:
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'dart:convert';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new HomePage(),
);
}
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: const Text("Native Code from Dart"),
),
body: new MyHomePage(title: ""),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _state = "Waiting results...";
static const platform = const MethodChannel("flutter_apple_pay");
_MyHomePageState() {
platform.setMethodCallHandler(_receiveFromHost);
}
// #override
// void initState() {
// platform.setMethodCallHandler(_receiveFromHost);
// super.initState();
// }
Future<dynamic> _receiveFromHost(MethodCall call) async {
List certificatesBase64Encoded;
String nonceBase64Encoded;
String nonceSignatureBase64Encoded;
String state;
try {
print(call.method);
if (call.method == "sendGenerateRequestWithData") {
final String data = call.arguments;
final jData = jsonDecode(data);
certificatesBase64Encoded = jData['certificatesBase64Encoded'];
nonceBase64Encoded = jData['nonceBase64Encoded'];
nonceSignatureBase64Encoded = jData['nonceSignatureBase64Encoded'];
print(certificatesBase64Encoded);
print(nonceBase64Encoded);
print(nonceSignatureBase64Encoded);
state = "sendGenerateRequestWithData";
platform.invokeMethod("SendTokenizationData", "TokenizationDataString");
} else if (call.method == "sendDidFinishAdding") {
final String result = call.arguments;
print(result);
state = result;
}
} on PlatformException catch (e) {
print(e);
}
setState(() {
_state = state;
});
print(_state);
}
Future<void> _checkCardState() async {
String cardState;
const primaryAccountIdentifiers = ["a", "b"];
try {
final String result = await platform.invokeMethod(
"checkCardState", primaryAccountIdentifiers);
cardState = result;
} on PlatformException catch (e) {
cardState = "Failed to Invoke: '${e.message}'.";
}
setState(() {
_state = cardState;
});
}
Future<void> _startApplePay() async {
const _cardNetwork = "cn/AMEX";
const _cardHolderName = "pero peric";
const _primaryAccountIdentifier = "a";
const _primaryAccountSuffix = "1234";
const _localizedDescription = "AMEX";
Map<String, dynamic> resultMap = Map();
resultMap['cardNetwork'] = _cardNetwork;
resultMap['cardHolderName'] = _cardHolderName;
resultMap['primaryAccountIdentifier'] = _primaryAccountIdentifier;
resultMap['primaryAccountSuffix'] = _primaryAccountSuffix;
resultMap['localizedDescription'] = _localizedDescription;
platform.invokeMethod("startApplePay", resultMap);
}
#override
Widget build(BuildContext context) {
return Material(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
child: Text('Check Card State'),
onPressed: _checkCardState,
),
ElevatedButton(
child: Text('Start Apple Pay'),
onPressed: _startApplePay,
),
Text(_state),
],
),
),
);
}
}
Thanks!

Load and read data from Json file

I create simple app get data of marker from json file and draw them.
The code below is get data from data.json and add to the list of marker.
I got problem. I can't get data from json file and add it to my marker list. How can I do that?
My main.dart code
class MapSample extends StatefulWidget {
#override
State<MapSample> createState() => MapSampleState();
}
class MapSampleState extends State<MapSample> {
#override
void initState() {
var location = Location();
FutureBuilder(
future:
DefaultAssetBundle.of(context).loadString('assets/data.json'),
builder: (context, snapshot) {
// Decode the JSON
var new_data = json.decode(snapshot.data.toString());
for (var i = 0; i < new_data.length; i++) {
location = Location(
id: new_data[i]['id'],
lat: new_data[i]['x'],
long: new_data[i]['y'],
);
locations.add(location);
//print(location.lat);
}
});
super.initState();
}
}
My data.json
[{
"rownum": 1,
"id": "E3E0D2C5-CB82-4AF3-8D5D-4CD323560F59",
"x": 10.99803453,
"y": 106.65676933,
}, {
"rownum": 2,
"id": "5FFB6736-7D1F-4B40-A397-32EB3128BC30",
"x": 10.99793271,
"y": 106.65666751,
},
I think this is what you are looking for.
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle;
void main() {
runApp(Test());
}
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
Future _future;
List<Location> locations;
Future<String> loadJson() async =>
await rootBundle.loadString('assets/data.json');
#override
void initState() {
_future = loadJson();
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: FutureBuilder(
future: _future,
builder: (context, snapshot) {
if (snapshot.hasData) {
for (var v in snapshot.data) {
locations.add(Location(
id: v['id'],
lat: v['x'],
long: v['y'],
));
}
return Text(snapshot.data);
} else {
return CircularProgressIndicator();
}
}),
),
);
}
}
class Location {
final String id;
final double lat;
final double long;
Location({this.id, this.lat, this.long});
}
Try this.
You have to add the data.json file in assests.
Then add in to pubspec.yaml file.
assets:
- assets/data.json
Then add this below code.
String jsonData = await DefaultAssetBundle.of(context).loadString("assets/data.json");
final jsonResult = json.decode(jsonData);

Bloc cannot return data in the dialog

I am developing a simple todo app using flutter with BloC pattern.
It has a ui to display TodoDetails.
When a user click a button, it show a new SimpleDialog.
I want to show some Tag list in the SimpleDialog like:
class AddEditTodoPage extends StatefulWidget {
final TodoRepository todoRepository;
final TagRepository tagRepository;
final Todo todo;
final SaveTodoBloc bloc;
AddEditTodoPage({this.todoRepository, this.tagRepository, this.todo})
: bloc = SaveTodoBloc(
todoRepository: todoRepository,
tagRepository: tagRepository,
todo: todo);
#override
State<StatefulWidget> createState() => _AddEditTodoPageState(todo: todo);
}
class _AddEditTodoPageState extends State<AddEditTodoPage> {
final Todo todo;
_AddEditTodoPageState({this.todo});
#override
Widget build(BuildContext context) {
return Center(
child: StreamBuilder<Tag>(
stream: widget.bloc.tag,
builder: (context, snapshot) {
final tag = snapshot.data;
return OutlineButton(
onPressed: () async {
final selectedTag = await showDialog<TagSelection>(
context: context,
builder: (context) => _showTagSelectDialog(context),
);
},
);
}},
);
}
_showTagSelectDialog(BuildContext context) => SimpleDialog(
title: Text("Select a Tag or create a new one"),
children: <Widget>[
StreamBuilder<List<Tag>>(
stream: widget.bloc.tags,
builder: (context, snapshot) {
final tagList = snapshot.data;
if (tagList == null || tagList.isEmpty) {
// This is always 'null'!!!
return SizedBox();
} else {
return ListView(
children: tagList.map(_buildTagName).toList(),
);
}
}),
],
);
Widget _buildTagName(Tag tag) => Text(tag.name);
}
So my bloc is getting the TagList like:
class SaveTodoBloc {
final TodoRepository todoRepository;
final TagRepository tagRepository;
final Todo todo;
SaveTodoBloc({this.todoRepository, this.tagRepository, this.todo}) {
if (tagRepository != null) {
_getTags();
}
}
final _getTagsSubject = PublishSubject<List<Tag>>();
Stream<List<Tag>> get tags => _getTagsSubject.stream;
Future<Null> _getTags() async {
await tagRepository.getAll().then((list) {
_getTagsSubject.add(list);
print("[SaveTodoBloc][JOS] _getTags - $list"); // It resturns correct list of Tags.
});
}
}
When I check the log, the bloc logic returns correct list of Tags.
But when I show the Dialog, it doesn't have list of tags.
The list is null.

Flutter: _InternalLinkedHashMap has no instance > method 'cast'

Sthg makes me crazy, I try to show json products in cards and it doesn't work. Here is what I tried so far:
Product class :
class Product {
final String id;
Product({this.id});
factory Product.fromJson(Map<String, dynamic> json) {
return new Product(
id: json['id'] as String
);
}
}
JSON:
Future loadProducts() async {
final response = await http.get('https://api.stripe.com/v1/products');
return response.body;
}
The json has the following structure (data contains a list of products):
Widget:
Widget get _homeView {
return new Column(
children: <Widget>[
new FutureBuilder(
future: loadProducts(),
builder: (context, snapshot) {
List<Product> products = parseJson(snapshot.data.toString());
return !products.isEmpty
? new ProductsList(product: products)
: new CircularProgressIndicator();
}
),
...
]
);
}
List<Product> parseJson(String response) {
final parsed = json.decode(response.toString()).cast<Map<String, dynamic>>();
return parsed.map<Product>((json) => new Product.fromJson(json)).toList();
}
ProductsList class:
class ProductsList extends StatelessWidget {
final List<Product> product;
ProductsList({Key key, this.product}) : super(key: key);
#override
Widget build(BuildContext context) {
return new ListView.builder(
itemCount: product == null ? 0 : product.length,
itemBuilder: (BuildContext context, int index) {
return new Card(
child: new Container(
children: <Widget>[
new Text(product[index].id),
],
)
);
}
);
}
}
Error :
Class '_InternalLinkedHashMap' has no instance
method 'cast' with matching arguments.
Edit 1 :
I tried :
Error :
This is my usual method for parsing a json list of objects (bit simpler but it works):
List<Product> parseJson(String response) {
List<Product> products = new List<Product>();
List jsonParsed = json.decode(response.toString());
for (int i = 0; i < jsonParsed.length; i++) {
products.add(new Product.fromJson(jsonParsed[i]));
}
return products;
}

Resources