I`m going to use data from a server in my application. For that, I will receive the data using json from my local server, but the problem is that data is null and it is not fetched by my code.
Here is the code :
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'dart:convert';
void main() {
runApp( MaterialApp(
home: MyHomePage(),
));
}
class MyHomePage extends StatefulWidget {
var title;
MyHomePage({Key key, this.title}) : super(key: key);
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Future<Base> _getBase() async {
var data = await http.get(Uri.encodeFull("http://192.168.1.13:5000/json"));
var jsonData = json.decode(data.body);
Base base = Base.fromJson(jsonData);
return base;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Hi'),
),
body: Container(
child: FutureBuilder(
future: _getBase(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.teal)),
),
);
} else {
return ListView.builder(
itemCount: snapshot.data.categories.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
subtitle: Text(snapshot.data.categories[index].category_id),
title: Text(snapshot.data.categories[index].devices[index].title),
leading: CircleAvatar(
// ignore: argument_type_not_assignable
// backgroundImage: NetworkImage(snapshot.data.devices[index].thumbnailUrl),
)
);
},
);
}
},
),
),
);
}
}
and here is the data model used for json:
class Base{
List <Category> array;
List<Category> categories;
Base( {this.categories});
factory Base.fromJson(Map<String,dynamic> parsedJson){
var list = parsedJson['categories'] as List;
List<Category> categoryList = list.map((i) => Category.fromJson(i)).toList();
return Base(
categories: categoryList
);
}
}
class Category {
int category_id,device_type_id,room_id;
List<Device_type> device_types;
List<Rooms> rooms;
List<Devices> devices;
Category({this.category_id,this.device_types,this.device_type_id,this.devices,this.rooms,this.room_id});
factory Category.fromJson(Map<String,dynamic>parsedJson){
var list1 = parsedJson['Device_types'] as List;
var list2 = parsedJson['Rooms'] as List;
var list3 = parsedJson['Devices'] as List;
List<Device_type> deviceTypeList =list1.map((i)=>Device_type.fromJson(i)).toList();
List<Rooms> roomsList =list2.map((i)=>Rooms.fromJson(i)).toList();
List<Devices> devicesList =list3.map((i)=>Devices.fromJson(i)).toList();
return Category(
category_id: parsedJson["category_id"],
device_type_id: parsedJson["device_type_id"],
room_id: parsedJson["room_id"],
device_types: deviceTypeList,
rooms : roomsList,
devices: devicesList
);
}
}
class Device_type {
int device_type_id, image , device_no;
String title ;
Device_type ({this.device_type_id,this.title,this.image,this.device_no});
factory Device_type.fromJson(Map<String,dynamic>parsedJson){
return Device_type(
device_type_id: parsedJson["device_type_id"],
title: parsedJson["title"],
image: parsedJson["image"],
device_no: parsedJson["device_no"],
);
}
}
class Rooms {
int id, image , device_no,roomcode;
String description,title ;
Rooms ({this.id,this.title,this.image,this.device_no,this.roomcode,this.description});
factory Rooms.fromJson(Map<String,dynamic> parsedJson){
return Rooms(
id: parsedJson["id"],
title:parsedJson["title"],
image: parsedJson["image"],
device_no: parsedJson["device_no"],
roomcode: parsedJson["roomcode"],
description: parsedJson["description"]
);
}
}
class Devices {
int device_id, image_path ,type,status,fav_flag, category_id;
String description,title ;
Devices ({this.device_id,this.title,this.image_path,
this.description,this.fav_flag,this.status,this.type,this.category_id});
factory Devices.fromJson(Map<String,dynamic> parsedJson){
return Devices(
device_id: parsedJson["device_id"],
title:parsedJson["title"],
image_path: parsedJson["image_path"],
type: parsedJson["type"],
status: parsedJson["status"],
fav_flag: parsedJson["fav_flag"],
category_id : parsedJson['category_id'],
description: parsedJson["description"]
);
}
}
for better understanding i put the image below:
And when I trace the project to find out where is the problem, I realized that it just loop one time, and so the data will be null forever, don't know why
Any help will be appreciated
Related
It makes no sense at this code. I am trying to grab some strings from the ALREADY INITIALIZED from the futurebuilder data, but can't do so. It gives me the data2 has not been initialized error. Here is data and data2, they are almost similiar, data works fine but data2 doesn't. Why is that?
late List<Album> data;
late List<String> data2;
Here is my code:
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
const List<String> list = <String>['One', 'Two', 'Three', 'Four'];
Future<List<Album>> fetchAlbum() async {
final response = await http.get(
Uri.parse('https://my-json-server.typicode.com/fluttirci/testJson/db'));
print(response);
Map<String, dynamic> userMap = jsonDecode(response.body);
if (response.statusCode == 200) {
return (userMap['employees'] as List)
.map((e) => Album.fromJson(e))
.toList();
} else {
throw Exception('Failed to load album');
}
}
class Album {
final int userId;
final int id;
final String title;
Album(this.userId, this.id, this.title);
Album.fromJson(Map<String, dynamic> json)
: userId = json['userId'],
id = json['id'],
title = json['title'];
Map<String, dynamic> toJson() => {
'userId': userId,
'id': id,
'title': title,
};
}
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late Future<Album> futureAlbum;
late Future<List<Album>> user;
late List<Album> data;
late List<String> data2;
#override
void initState() {
super.initState();
user = fetchAlbum();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
brightness: Brightness.dark,
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: const Text('Fetch Data Example'),
),
body: Column(children: <Widget>[
Expanded(
child: const DropdownButtonExample(),
),
Expanded(
child: FutureBuilder<List<Album>>(
future: user,
builder: (context, snapshot) {
if (snapshot.hasData) {
data = snapshot.data ?? [];
print('${data[4].title}');
return ListView.builder(
itemBuilder: (context, index) {
data2[index] = data[index].title;
return Column(children: [
Text(data[index].title ?? ""),
]);
},
itemCount: data.length,
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return Center(
child: const CircularProgressIndicator(),
);
},
),
)
]),
),
);
}
}
class DropdownButtonApp extends StatelessWidget {
const DropdownButtonApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('DropdownButton Sample')),
body: const Center(
child: DropdownButtonExample(),
),
),
);
}
}
class DropdownButtonExample extends StatefulWidget {
const DropdownButtonExample({super.key});
#override
State<DropdownButtonExample> createState() => _DropdownButtonExampleState();
}
class _DropdownButtonExampleState extends State<DropdownButtonExample> {
String dropdownValue = list.first;
#override
Widget build(BuildContext context) {
return DropdownButton<String>(
value: dropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: Colors.deepPurpleAccent,
),
onChanged: (String? value) {
// This is called when the user selects an item.
setState(() {
dropdownValue = value!;
});
},
items: list.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
}
For RangeError issue, your data2 is empty so you can search for index and pass your value to it, just add your string to it normally it will put that in right index, so change your listview's builder to this:
return ListView.builder(
itemBuilder: (context, index) {
data2.add(data[index].title);//<--- change this
return Column(children: [
Text(data[index].title ?? ""),
]);
},
itemCount: data.length,
);
I am a newbe in Flutter and I want to get data from my mysql and how to get the data of 'Facebook', 'Twitter', 'Youtube' from my mysql db ?
I want to load data into _tags1 widget from my mysql data.
final List<String> _list = [ 'Facebook', 'Twitter', 'Youtube'];
_list array value should be from my mysql data.
Here is my full code
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_tags/flutter_tags.dart';
void main() => runApp(MyApp());
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Tags Demo',
theme: ThemeData(
primarySwatch: Colors.blueGrey,
),
home: MyHomePage(title: 'Flutter Tags'),
);
}
}
class _MyHomePageState extends State<MyHomePage>{
bool _symmetry = false;
bool _removeButton = true;
bool _singleItem = true;
bool _startDirection = false;
bool _horizontalScroll = true;
int _column = 0;
double _fontSize = 14;
List _icon = [Icons.home, Icons.language, Icons.headset];
#override
void initState() {
super.initState();
_items = _list.toList();
}
List _items;
final List<String> _list = [ 'Facebook', 'Twitter', 'Youtube'];
final GlobalKey<TagsState> _tagStateKey = GlobalKey<TagsState>();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
child: _tags1,
)
)
);
}
Widget get _tags1 {
return Tags(
key: _tagStateKey,
symmetry: _symmetry,
columns: _column,
horizontalScroll: _horizontalScroll,
//verticalDirection: VerticalDirection.up, textDirection: TextDirection.rtl,
heightHorizontalScroll: 60 * (_fontSize / 14),
itemCount: _items.length,
itemBuilder: (index) {
final item = _items[index];
return ItemTags(
key: Key(index.toString()),
index: index,
title: item,
pressEnabled: true,
activeColor: Colors.blueGrey[600],
singleItem: _singleItem,
splashColor: Colors.green,
combine: ItemTagsCombine.withTextBefore,
image: index > 0 && index < 5
? ItemTagsImage(
//image: AssetImage("img/p$index.jpg"),
child: Image.network(
"http://www.clipartpanda.com/clipart_images/user-66327738/download",
width: 16 * _fontSize / 14,
height: 16 * _fontSize / 14,
))
: (1 == 1
? ItemTagsImage(
image: NetworkImage(
"https://d32ogoqmya1dw8.cloudfront.net/images/serc/empty_user_icon_256.v2.png"),
)
: null),
icon: (item == '0' || item == '1' || item == '2')
? ItemTagsIcon(
icon: _icon[int.parse(item)],
)
: null,
removeButton: _removeButton
? ItemTagsRemoveButton(
onRemoved: () {
setState(() {
_items.removeAt(index);
});
return true;
},
)
: null,
textScaleFactor:
utf8.encode(item.substring(0, 1)).length > 2 ? 0.8 : 1,
textStyle: TextStyle(
fontSize: _fontSize,
),
onPressed: (item) => print(item),
);
},
);
}
}
You need to do a Get request on your API endpoint. This endpoint will return your JSON with your string list. After receiving, you need to decode the json to your List. Here is an example:
// Getting API Data using Dio package:
var response = await dio.get(yourApiUrl);
//parsing your json to string list
List<String> stringList = (jsonDecode(response) as List<dynamic>).cast<String>();
I am on Vipin Vijayan's tutorial on parsing JSON in ListView following Flutter's fetch data from the internet cookbook and getting the following error:
═══════════════════════════════════ Exception caught by widgets library
═══════════════════════════════════ The following assertion was thrown
building MyApp(dirty, state: _MyAppState#a2d98): Failed assertion:
boolean expression must not be null
The relevant error-causing widget was MyApp
package:le_moineau/main.dart:35 When the exception was thrown, this
was the stack
#0 _MyAppState.build package:le_moineau/main.dart:70
#1 StatefulElement.build package:flutter/…/widgets/framework.dart:4802
#2 ComponentElement.performRebuild package:flutter/…/widgets/framework.dart:4685
#3 StatefulElement.performRebuild package:flutter/…/widgets/framework.dart:4857
#4 Element.rebuild package:flutter/…/widgets/framework.dart:4379 ...
Here is the code to my Users.dart parsed using https://app.quicktype.io/
// To parse this JSON data, do
//
// final users = usersFromJson(jsonString);
import 'dart:convert';
List<User> usersFromJson(String str) =>
List<User>.from(json.decode(str).map((x) => User.fromJson(x)));
String usersToJson(List<User> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class User {
User({
this.userId,
this.id,
this.title,
this.completed,
});
int userId;
int id;
String title;
bool completed;
factory User.fromJson(Map<String, dynamic> json) => User(
userId: json["userId"],
id: json["id"],
title: json["title"],
completed: json["completed"],
);
Map<String, dynamic> toJson() => {
"userId": userId,
"id": id,
"title": title,
"completed": completed,
};
}
and here's my main.dart code:
import 'dart:async';
//import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'others/Users.dart';
class MyHttpOverrides extends HttpOverrides {
#override
HttpClient createHttpClient(SecurityContext context) {
return super.createHttpClient(context)
..badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
}
}
Future<List<User>> getUsers() async {
final response =
await http.get(Uri.https('jsonplaceholder.typicode.com', 'todos'));
//await http.get("https://192.168.1.4:8081/json/todos.json");
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
final List<User> users = usersFromJson(response.body);
return users;
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load users');
}
}
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
MyApp({Key key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<User> _users;
bool _loading;
#override
void initState() {
HttpOverrides.global = new MyHttpOverrides();
super.initState();
_loading = true;
getUsers().then((users) {
setState(() {
_users = users;
_loading = false;
});
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Fetch Data Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text(_loading ? 'Loading...' : 'Users'),
),
body: Container(
color: Colors.white,
child: ListView.builder(
itemCount: null == _users ? 0 : _users.length,
itemBuilder: (context, index) {
User user = _users[index];
return ListTile(
title: Text('This is a test'),
subtitle: Text(user.title),
);
}),
),
),
);
}
}
I get the same error even when I use Vipin's stock Widget Build code. Could someone take a look and give me some advice please?
try to initialize true value in bool variable
bool _loading = true;
and remove _loading = true; in initState()
Because Null Safety coming with Flutter 2.0.x, bool _loading; is not permitted, so you do either bool? _loading; or bool _loading = true;. ? means your variable accepts null-values.
UPDATE: Inserting code
NetService
class NetService {
...
static Future<T?> getJson<T>(String url, {int okCode = 200}) {
return http.get(Uri.parse(url))
.then((response) {
if (response.statusCode == okCode) {
return jsonDecode(response.body) as T;
}
_printDataNotOK(response);
return null;
})
.catchError((err) => _printError(err));
}
....
}
json_placeholder_service.dart
import 'dart:async';
import 'package:jsonplaceholder/services/networking.dart';
class JsonPlaceholderService {
static const _baseUrl = 'https://jsonplaceholder.typicode.com';
/* ---------------------------------------------------------------------------- */
static Future<List?> _doGet(String path) async {
return await NetService.getJson<List>(_baseUrl + path)
.whenComplete(() => print('\nFetching done!'));
}
/* ---------------------------------------------------------------------------- */
static Future<List?> fetchTodos() => _doGet('/todos');
}
home_page.dart
import 'package:flutter/material.dart';
import 'package:jsonplaceholder/services/json_placeholder_service.dart';
class HomePage extends StatelessWidget {
/* ---------------------------------------------------------------------------- */
const HomePage({Key? key}) : super(key: key);
/* ---------------------------------------------------------------------------- */
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Hi!'),
centerTitle: true,
),
body: SingleChildScrollView(
child: FutureBuilder<List?>(
future: JsonPlaceholderService.fetchTodos(),
builder: (context, snapshot) {
if (snapshot.hasError) return Text(snapshot.error.toString());
if (snapshot.connectionState == ConnectionState.done) {
var data = snapshot.data;
if (data != null && data.isNotEmpty) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: List<Widget>.generate(data.length, (i) {
var item = data[i];
return Text('${item['userId']} - ${item['id']} - ${item['title']}');
}),
);
}
return Text('No data received!');
}
return CircularProgressIndicator();
},
),
),
);
}
}
Result:
here is the response
{
"overview": "A ticking-time-bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking new form of therapy. Their concept catches on, with underground "fight clubs" forming in every town, until an eccentric gets in the way and ignites an out-of-control spiral toward oblivion.",
"title": "Fight Club",
}
the model
class Movies {
String title;
String overview;
Movies(
{this.title , this.overview});
factory Movies.fromJson(Map <String, dynamic> parsedJson){
return Movies(title: parsedJson['title'] , overview: parsedJson['overview']);
}
}
and
Future <List<Movies>> fetchMovies () async {
var response = await http.get(url);
var jsonData = jsonDecode(response.body) as List ;
List<Movies> movies = jsonData.map((e) => Movies.fromJson(e)).toList();
print(movies.length);
return movies;
}
I get this error (Unhandled Exception: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List' in type cast) no matter what i do
You tried to cast jsonData as List but the decoder says it's of type Map (Also your response shows its of type Map)
Future <List<Movies>> fetchMovies () async {
var response = await http.get(url);
var jsonData = jsonDecode(response.body);
if(jsonData is List) //check if it's a List
return List<Movies>.from(jsonData.map(map) => Movies.fromJson(map));
else if(jsonData is Map) //check if it's a Map
return [Movies.fromJson(jsonData)]; //return a List of length 1
}
You can copy paste run full code below
You can use moviesFromJson and display with FutureBuilder
code snippet
List<Movies> moviesFromJson(String str) =>
List<Movies>.from(json.decode(str).map((x) => Movies.fromJson(x)));
if (response.statusCode == 200) {
return moviesFromJson(jsonString);
working demo
full code
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
List<Movies> moviesFromJson(String str) =>
List<Movies>.from(json.decode(str).map((x) => Movies.fromJson(x)));
String moviesToJson(List<Movies> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Movies {
Movies({
this.overview,
this.title,
});
String overview;
String title;
factory Movies.fromJson(Map<String, dynamic> json) => Movies(
overview: json["overview"],
title: json["title"],
);
Map<String, dynamic> toJson() => {
"overview": overview,
"title": title,
};
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
Future<List<Movies>> _future;
Future<List<Movies>> fetchMovies() async {
String jsonString = '''
[{
"overview" : "with underground \\"fight clubs\\" forming in every town, until an eccentric gets in the way and ignites an out-of-control spiral toward oblivion",
"title" : "Fight Club"
},
{
"overview" : "test overview",
"title" : "test title"
}
]
''';
var response = http.Response(jsonString, 200);
if (response.statusCode == 200) {
return moviesFromJson(jsonString);
} else {
print(response.statusCode);
}
}
#override
void initState() {
_future = fetchMovies();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: FutureBuilder(
future: _future,
builder: (context, AsyncSnapshot<List<Movies>> snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.none:
return Text('none');
case ConnectionState.waiting:
return Center(child: CircularProgressIndicator());
case ConnectionState.active:
return Text('');
case ConnectionState.done:
if (snapshot.hasError) {
return Text(
'${snapshot.error}',
style: TextStyle(color: Colors.red),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return Card(
elevation: 6.0,
child: Padding(
padding: const EdgeInsets.only(
top: 6.0,
bottom: 6.0,
left: 8.0,
right: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(snapshot.data[index].title),
Spacer(),
Expanded(
child: Text(
snapshot.data[index].overview,
),
),
],
),
));
});
}
}
}));
}
}
Just check out he answer
[
{
"overview":"A ticking-time-bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking new form of therapy. Their concept catches on, with underground \"fight clubs\" forming in every town, until an eccentric gets in the way and ignites an out-of-control spiral toward oblivion.",
"title":"Fight Club"
},
{
"overview":"A ticking-time-bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking new form of therapy. Their concept catches on, with underground fight clubs forming in every town, until an eccentric gets in the way and ignites an out-of-control spiral toward oblivion.",
"title":"second Club"
}
]
Model
// To parse this JSON data, do
//
// final movies = moviesFromJson(jsonString);
import 'dart:convert';
List<Movies> moviesFromJson(String str) => List<Movies>.from(json.decode(str).map((x) => Movies.fromJson(x)));
String moviesToJson(List<Movies> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Movies {
Movies({
this.overview,
this.title,
});
String overview;
String title;
factory Movies.fromJson(Map<String, dynamic> json) => Movies(
overview: json["overview"],
title: json["title"],
);
Map<String, dynamic> toJson() => {
"overview": overview,
"title": title,
};
}
ui page :
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:json_parsing_example/models.dart';
// To parse this JSON data, do
//
// final user = userFromJson(jsonString);
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Users'),
);
}
}
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> {
bool _isLoading = false;
List<Movies> dataList = List();
Future<String> loadFromAssets() async {
return await rootBundle.loadString('json/parse.json');
}
#override
void initState() {
super.initState();
getData();
}
getData() async {
setState(() {
_isLoading = true;
});
String jsonString = await loadFromAssets();
final movies = moviesFromJson(jsonString);
dataList = movies;
setState(() {
_isLoading = false;
});
}
// In your case you just check out this code check out the model class
/* Future <List<Movies>> fetchMovies () async {
var response = await http.get(url);
return moviesFromJson(response.body);
} */
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: _isLoading
? Center(
child: CircularProgressIndicator(),
)
: Container(
child: ListView.builder(
itemCount: dataList.length,
shrinkWrap: true,
itemBuilder: (context, i) {
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(dataList[i].overview),
));
}),
),
);
}
}
And on thing to tell is the value for the overview has the double quotes which is why there might be some parsing problem just check the code and let me know if it works.
I am returning data from MySQL in JSON using this piece of code
while($row = mysqli_fetch_assoc($queryResult)) {
$resultArray[]=$row;
}
echo json_encode($resultArray);
The result is in this format
[{
"reg_number": "FA16-BCS-106",
"teacher_id": "1",
"qr_code": "jamshaid",
"course_name": "COURSE 1"
}, {
"reg_number": "FA16-BCS-106",
"teacher_id": "EMP_FA10_10",
"qr_code": "jamoo",
"course_name": "COURSE 2"
}]
I am decoding the response and storing it in a list using this method which is working fine.
class Student {
final String reg_number;
final String teacher_id;
final String qr_code;
final String course_name;
Student({this.reg_number, this.teacher_id, this.qr_code, this.course_name});
factory Student.fromJson(Map<String, dynamic> json) {
return Student(
reg_number: json['reg_number'],
teacher_id: json['teacher_id'],
qr_code: json['qr_code'],
course_name: json['course_name'],
);
}
}
final parsed =
json.decode(jsonResponse.body).cast<Map<String, dynamic>>();
List<Student> st =
parsed.map<Student>((json) => Student.fromJson(json)).toList();
I am trying to store this List of objects of Student class in SharedPreference using version ^0.5.6. There is no direct method available for this. I've tried using this method but having the following error.
Unhandled Exception: type 'List' is not a subtype of type 'Map'
jsonResponse.body is supposed to be a string but it is reading it as List<dynamic>. Why is that happening? Am I doing anything wrong while parsing the result? Thanks
Here is a simple example created for you to understand how to do this. This is ok for small list but if you have a large list, I dont recommend this because of we are doing too much stuff here.
import 'dart:convert';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class Todo {
final String title;
final String description;
Todo(this.title, this.description);
Todo.fromJson(Map<String, dynamic> map) :
title = map["title"],
description = map["description"];
Map<String, dynamic> toMap() => {
"title": title,
"description": description
};
}
void main() {
runApp(MaterialApp(
title: 'Passing Data',
home: HomePage(
todos: List.generate(
20, (i) => Todo(
'Todo $i',
'A description of what needs to be done for Todo $i',
),
),
),
));
}
class HomePage extends StatelessWidget {
final List<Todo> todos;
HomePage({this.todos}) {
saveTodos();
}
void saveTodos() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> values = todos.map((item) => json.encode(item.toMap())).toList();
prefs.setStringList("todos", values);
}
#override
Widget build(BuildContext context) {
return TodosScreen();
}
}
class TodosScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _StateTodosScreen();
}
}
class _StateTodosScreen extends State<TodosScreen> {
Future<List<Todo>> getTodos() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> values = prefs.getStringList("todos");
return values.map((item) => Todo.fromJson(json.decode(item))).toList();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Todos'),
),
body: FutureBuilder(
future: getTodos(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data[index].title),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailScreen(todo: snapshot.data[index]),
),
);
},
);
},
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
);
}
}
class DetailScreen extends StatelessWidget {
final Todo todo;
DetailScreen({Key key, #required this.todo}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(todo.title),
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Text(todo.description),
),
);
}
}
But you can simply encode your complete json and store, there will not be much work then, but if it is a complex json you have to handle that also.