Related
i'm learning flutter recently, and i have a problem. How display nested json file in listview in flutter ?
On internet i see a lots of example but it's with an url of an api and i don't want use api. I'm in local.
I think the problem is not my parse, but i don't know so, below you can see my code.
array.json
[
{
"jp": {
"name": "jp",
"password": "pawwordTest",
"maxtun": 0,
"email": "jp#france.fr",
"date": {
"build": "test1",
"first_cnx": "test2"
}
}
}
]
array.dart
class JP {
final String name;
final String password;
final int maxtun;
final String email;
final Date date;
JP({
required this.name,
required this.password,
required this.maxtun,
required this.email,
required this.date,
});
factory JP.fromJson(Map<String, dynamic> json){
return JP(
name: json['name'],
password: json['password'],
maxtun: json['maxtun'],
email: json['email'],
date: Date.fromJson(json['date']),
);
}
}
class Date{
final String build;
final String firstCNX;
Date({required this.build, required this.firstCNX});
factory Date.fromJson(Map<String, dynamic> json){
return Date(
build: json['build'],
firstCNX: json['first_cnx']
);
}
}
And event_page.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'dart:async' show Future;
//import 'package:flutter/material.dart' show rootBundle;
import 'package:array_json/array.dart';
import 'package:flutter/services.dart';
class EventPage extends StatefulWidget {
const EventPage({Key? key}) : super(key: key);
#override
State<EventPage> createState() => _EventPageState();
}
class _EventPageState extends State<EventPage> {
List<JP> testJson = [];
Future<void> readJson() async{
final String response = await rootBundle.loadString("assets/array.json");
final informationData = await json.decode(response);
var list = informationData['jp'] as List<dynamic>;
setState(() {
testJson = [];
testJson = list.map((e) => JP.fromJson(e)).toList();
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leadingWidth: 100,
leading: ElevatedButton.icon(
onPressed: () => Navigator.of(context).pop(),
icon: const Icon(Icons.arrow_back_ios,
color: Colors.blue,
),
label: const Text("Back",
style: TextStyle(color: Colors.blue),
),
style: ElevatedButton.styleFrom(
elevation: 0,
backgroundColor: Colors.transparent,
),
),
centerTitle: true,
title: const Text("Load and Read JSON File",
style: TextStyle(color: Colors.black54),
),
backgroundColor: Colors.white,
),
body: Column(
children: [
Padding(padding: EdgeInsets.all(15.0),
child: ElevatedButton(onPressed: readJson,
child: const Text("Load Informations")),
),
Expanded(
child: ListView.builder(
itemCount: testJson.length,
itemBuilder: (BuildContext context, index){
final x = testJson[index];
return Container(
padding: EdgeInsets.all(10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("test : ${x.name}"),
Text(x.password),
Text(x.maxtun.toString()),
Text(x.email),
const SizedBox(
height: 5.0,
),
const Text("Date : ",
style: TextStyle(fontSize: 16.0, fontWeight: FontWeight.bold),
),
Text(x.date.build),
Text(x.date.firstCNX),
const SizedBox(
height: 5.0,
),
],
),
);
}
),
),
],
),
);
}
}
Help me please, i'm sure, i'm not missing much but it's the question
informationData['jp'] can't be a List, it's a Map, try this code instead:
Future<void> readJson() async{
final String response = await rootBundle.loadString("assets/array.json");
final informationData = json.decode(response) as List;
setState(() {
testJson = informationData.map<JP>((e) => JP.fromJson(e['jp'])).toList();
});
}
actually the problem you have is that the json file has a list and you are accessing it like map so that is causing issue change your json file content with this that will solve your problem
{
"jp": [
{
"name": "jp",
"password": "pawwordTest",
"maxtun": 0,
"email": "jp#france.fr",
"date": {
"build": "test1",
"first_cnx": "test2"
}
}
]
}
I'm trying to get some images from an API but facing this error
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: type 'String' is not a subtype of type 'Map<dynamic, dynamic>'
The Json from the API looks like this and it's from www.themoviedb.org:
{
"page": 1,
"results": [
{
"adult": false,
"backdrop_path": "/qxeqKcVBWnQxUp1w6fwWcxZEA6m.jpg",
"genre_ids": [
28,
12,
14
],
"id": 436270,
"original_language": "en",
"original_title": "Black Adam",
"overview": "Nearly 5,000 years after he was bestowed with the almighty powers of the Egyptian gods—and imprisoned just as quickly—Black Adam is freed from his earthly tomb, ready to unleash his unique form of justice on the modern world.",
"popularity": 6041.545,
"poster_path": "/3zXceNTtyj5FLjwQXuPvLYK5YYL.jpg",
"release_date": "2022-10-19",
"title": "Black Adam",
"video": false,
"vote_average": 7.2,
"vote_count": 425
},
],
"total_pages": 35601,
"total_results": 712013
}
Here is the code:
Movie
class Movie {
final int id;
final String name;
final String description;
final String? posterPath;
//<editor-fold desc="Data Methods">
Movie({
required this.id,
required this.name,
required this.description,
this.posterPath,
});
Movie copyWith({
int? id,
String? name,
String? description,
String? posterPath,
}) {
return Movie(
id: id ?? this.id,
name: name ?? this.name,
description: description ?? this.description,
posterPath: posterPath ?? this.posterPath,
);
}
factory Movie.fromJson(Map<String, dynamic> map) {
return Movie(
id: map['id'] as int,
name: map['title'] as String,
description: map['overview'] as String,
posterPath: map['poster_path'] as String,
);
}
// Poster url ****************************************************************
String posterUrl() {
Api api = Api();
return api.baseUrl + posterPath!;
}
//</editor-fold>
}
API
class Api {
final String apiKey = ApiKey.apiKey;
final String baseUrl = "https://developers.themoviedb.org/3";
final String baseImageUrl = "https://image.tmdb.org/t/p/w500/";
final String baseVideoUrl = "https://www.youtube.com/watch?=v";
}
ApiKey
class ApiKey {
static String apiKey = "my_api_key";
}
ApiService
class ApiService {
final Api api = Api();
final Dio dio = Dio();
Future<Response> getData(String path, {Map<String, dynamic>? params}) async {
String url = api.baseUrl + path;
Map<String, dynamic> query = {
"api_key": api.apiKey,
"language": "en-US",
};
if(params != null) {
query.addAll(params);
}
final response = await dio.get(url, queryParameters: query);
if(response.statusCode == 200) {
return response;
}
else {
throw response;
}
}
//****************************************************************************
// Get popular movies
//****************************************************************************
Future getPopularMovies({required int pageNumber}) async{
Response response = await getData(
"/movie/popular",
params: {
"page": pageNumber,
}
);
if(response.statusCode == 200){
Map data = response.data; // <--------------------------- Problem is here
List<dynamic> results = data["results"]; // <--------------------------- And here
List<Movie> movies = [];
for(Map<String, dynamic> json in results){
Movie movie = Movie.fromJson(json);
movies.add(movie);
}
return movies;
}
else{
throw response;
}
}
}
HomeScreen
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<Movie>? movies;
#override
void initState() {
super.initState();
getMovies();
}
//****************************************************************************
// Get movies
//****************************************************************************
void getMovies(){
ApiService().getPopularMovies(pageNumber: 1)
.then((movieList){
setState(() {
movies = movieList;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: kBackgroundColor,
appBar: AppBar(
backgroundColor: kBackgroundColor,
leading: Image.asset(
"assets/images/netflix_logo_2.png"
),
),
body: ListView(
children: [
Container(
height: 500,
color: Colors.red,
child: movies == null
? const Center()
: Image.network(
movies![0].posterUrl(),
fit: BoxFit.cover,
),
),
const SizedBox(height: 15,),
Text("Current trends",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold
),
),
const SizedBox(height: 5,),
SizedBox(
height: 160,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (context, index) {
return Container(
width: 110,
margin: const EdgeInsets.only(right: 8),
color: Colors.yellow,
child: Center(
child: Text(index.toString()),
),
);
},
),
),
const SizedBox(height: 15,),
Text("Currently in cinema",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold
),
),
const SizedBox(height: 5,),
SizedBox(
height: 320,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (context, index) {
return Container(
width: 220,
margin: const EdgeInsets.only(right: 8),
color: Colors.blue,
child: Center(
child: Text(index.toString()),
),
);
},
),
),
const SizedBox(height: 15,),
Text("Available soon",
style: GoogleFonts.poppins(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold
),
),
const SizedBox(height: 5,),
SizedBox(
height: 160,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 10,
itemBuilder: (context, index) {
return Container(
width: 110,
margin: const EdgeInsets.only(right: 8),
color: Colors.green,
child: Center(
child: Text(index.toString()),
),
);
},
),
),
],
),
);
}
}
What I've tried:
I've tried to replace Map with var in ApiService but the problem isn't solved because another error is shown in the logcat doing this:
[ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'
Thanks in advance for the help
in the ApiService file
first import
import 'dart:convert';
then in the same line where the problem occurred add jsonDecode, like this
Map data = jsonDecode(response.data);
#hamza aboshhiwa thanks for the answer
I finally found, the 2 mistakes were in Movie and API replacing:
String posterUrl() {
Api api = Api();
return api.baseUrl + posterPath!;
}
By:
String posterUrl() {
Api api = Api();
return api.baseImageUrl + posterPath!;
}
And:
class Api {
final String apiKey = ApiKey.apiKey;
final String baseUrl = "https://developers.themoviedb.org/3";
final String baseImageUrl = "https://image.tmdb.org/t/p/w500/";
final String baseVideoUrl = "https://www.youtube.com/watch?=v";
}
By:
class Api {
final String apiKey = ApiKey.apiKey;
final String baseUrl = "https://api.themoviedb.org/3"; //<-----------------
final String baseImageUrl = "https://image.tmdb.org/t/p/w500/";
final String baseVideoUrl = "https://www.youtube.com/watch?=v";
}
Now it works
I'm trying to make an educational application in Turkish and i want to list the topics on my homepage. I created a sketch of my homepage and i want to print the texts inside the cards by taking the parts named "konuBasligi" from the local json file.
Before sharing the codes, I would like to share the existing design and json file with you:
{
"bende": {
"dersler": [{
"id": 0,
"dersAdi": "Türkçe"
}, {
"id": 1,
"dersAdi": "Matematik"
}, {
"id": 2,
"dersAdi": "Tarih",
"konular": [{
"konuId": 0,
"konuBasligi": "İslamiyet Öncesi Türk Tarihi",
"altkonular": [{
"altKonuId": 0,
"altKonuBasligi": "Giriş",
"basliklar": [{
"baslikId": 0,
"baslikAdi": "Türk Adının Anlamı"
}, {
"baslikId": 1,
"baslikAdi": "İlk Yerleşim Yerleri"
}, {
"baslikId": 2,
"baslikAdi": "Göçler"
}]
}, {
"altKonuId": 1,
"altKonuBasligi": "İlk Türk Toplulukları ve Devletleri",
"basliklar": [{
"baslikId": 0,
"baslikAdi": "İskitler"
}, {
"baslikId": 1,
"baslikAdi": "Asya Hun Devleti"
}, {
"baslikId": 2,
"baslikAdi": "Avrupa Hun Devleti"
}]
}, {
"altKonuId": 2,
"altKonuBasligi": "Diğer Türk Toplulukları ve Devletleri",
"basliklar": [{
"baslikId": 0,
"baslikAdi": "Avatarlar"
}, {
"baslikId": 1,
"baslikAdi": "Karluklar"
}, {
"baslikId": 2,
"baslikAdi": "Kırgızlar"
}]
}, {
"altKonuId": 3,
"altKonuBasligi": "Kültür ve Medeniyet",
"basliklar": [{
"baslikId": 0,
"baslikAdi": "Hükümdarlar"
}, {
"baslikId": 1,
"baslikAdi": "Devlet Yönetimi"
}, {
"baslikId": 2,
"baslikAdi": "Ordu"
}]
}]
}, {
"konuId": 1,
"konuBasligi": "İlk Türk İslam Devletleri"
}, {
"konuId": 2,
"konuBasligi": "Türkiye Tarihi"
}, {
"konuId": 3,
"konuBasligi": "Osmanlı Tarihi"
}, {
"konuId": 4,
"konuBasligi": "Kurtuluş Savaşı"
}, {
"konuId": 5,
"konuBasligi": "Çağdaş Türk ve Dünya Tarihi"
}]
}, {
"id": 3,
"dersAdi": "Coğrafya"
}, {
"id": 4,
"dersAdi": "Vatandaşlık"
}, {
"id": 5,
"dersAdi": "Genel Kültür"
}, {
"id": 6,
"dersAdi": "Program Geliştirme"
}, {
"id": 7,
"dersAdi": "Rehberlik ve Özel Eğitim"
}, {
"id": 8,
"dersAdi": "Öğretim Yöntem ve Teknikleri"
}, {
"id": 9,
"dersAdi": "Ölçme ve Değerlendirme"
}, {
"id": 10,
"dersAdi": "Öğrenme Psikolojisi"
}, {
"id": 11,
"dersAdi": "Gelişim Psikolojisi"
}]
}
}
I think I read the data using "FutureBuilder" and "DefaultAssetBundle" from the video I watched and the articles I read, but I got stuck in the "children" part in "Gridview.count". I couldn't adapt it myself because they usually use "Listview.builder".
The code of the design image I shared contains too many files such as "screens", "utils". For this, I created a file with only the parts related to my question and its contents are as follows:
import 'dart:convert';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test',
home: Scaffold(
appBar: AppBar(
title: const Text('Gridview From JSON'),
),
body: FutureBuilder(
future: DefaultAssetBundle.of(context).loadString('data/veri.json'),
builder: (context, snapshot) {
var read = json.decode(snapshot.data.toString());
return GridView.count(
crossAxisCount: 2,
padding:
const EdgeInsets.only(left: 12.0, right: 12.0, top: 8.0),
scrollDirection: Axis.vertical,
childAspectRatio: 1,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
),
],
);
}),
),
);
}
}
Thank you in advance for your help...
I Just spent some time on your question to recreate the example.
Step1: You need to convert the JSON to a model, which Can be done with the help of https://app.quicktype.io/ and save it as model.dart
// model.dart
// To parse this JSON data, do
//
// final reportData = reportDataFromJson(jsonString);
import 'dart:convert';
import 'package:flutter/material.dart';
ReportData reportDataFromJson(String str) =>
ReportData.fromJson(json.decode(str));
String reportDataToJson(ReportData data) => json.encode(data.toJson());
class ReportData {
ReportData({
this.bende,
});
Bende? bende;
factory ReportData.fromJson(Map<String, dynamic> json) => ReportData(
bende: Bende.fromJson(json["bende"]),
);
Map<String, dynamic> toJson() => {
"bende": bende!.toJson(),
};
}
class Bende {
Bende({
this.dersler,
});
List<Dersler>? dersler;
factory Bende.fromJson(Map<String, dynamic> json) => Bende(
dersler:
List<Dersler>.from(json["dersler"].map((x) => Dersler.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"dersler": List<dynamic>.from(dersler!.map((x) => x.toJson())),
};
}
class Dersler {
Dersler({
this.id,
this.dersAdi,
this.konular,
});
int? id;
String? dersAdi;
List<Konular>? konular;
factory Dersler.fromJson(Map<String, dynamic> json) => Dersler(
id: json["id"],
dersAdi: json["dersAdi"],
konular: json["konular"] == null
? null
: List<Konular>.from(
json["konular"].map((x) => Konular.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"dersAdi": dersAdi,
"konular": konular == null
? null
: List<dynamic>.from(konular!.map((x) => x.toJson())),
};
}
class Konular {
Konular({
this.konuId,
this.konuBasligi,
this.altkonular,
});
int? konuId;
String? konuBasligi;
List<Altkonular>? altkonular;
factory Konular.fromJson(Map<String, dynamic> json) => Konular(
konuId: json["konuId"],
konuBasligi: json["konuBasligi"],
altkonular: json["altkonular"] == null
? null
: List<Altkonular>.from(
json["altkonular"].map((x) => Altkonular.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"konuId": konuId,
"konuBasligi": konuBasligi,
"altkonular": altkonular == null
? null
: List<dynamic>.from(altkonular!.map((x) => x.toJson())),
};
}
class Altkonular {
Altkonular({
this.altKonuId,
this.altKonuBasligi,
this.basliklar,
});
int? altKonuId;
String? altKonuBasligi;
List<Basliklar>? basliklar;
factory Altkonular.fromJson(Map<String, dynamic> json) => Altkonular(
altKonuId: json["altKonuId"],
altKonuBasligi: json["altKonuBasligi"],
basliklar: List<Basliklar>.from(
json["basliklar"].map((x) => Basliklar.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"altKonuId": altKonuId,
"altKonuBasligi": altKonuBasligi,
"basliklar": List<dynamic>.from(basliklar!.map((x) => x.toJson())),
};
}
class Basliklar {
Basliklar({
this.baslikId,
this.baslikAdi,
});
int? baslikId;
String? baslikAdi;
factory Basliklar.fromJson(Map<String, dynamic> json) => Basliklar(
baslikId: json["baslikId"],
baslikAdi: json["baslikAdi"],
);
Map<String, dynamic> toJson() => {
"baslikId": baslikId,
"baslikAdi": baslikAdi,
};
}
Step2: Create a class to get Data from the model, something like
class DataFromReport {
static Future<ReportData> getDataLocally(BuildContext context) async {
final assetBundle = DefaultAssetBundle.of(context);
final data = await assetBundle.loadString('data/veri.json');
final reportData = reportDataFromJson(data);
return reportData;
}
}
Step3: Create a method to get the list of "konuBasligi" from ReportData
//getting list of konular from ReportData
List<String> getkonular(ReportData? data) {
List<String> listkonular = [];
//konular is not present in all dersler
// so fist get the length of dersler
int length = data?.bende?.dersler?.length ?? 0;
for (var i = 0; i < length; i++) {
final ders = data?.bende?.dersler?.elementAt(i);
//now get the number of konular
int length2 = ders?.konular?.length ?? 0;
for (var j = 0; j < length2; j++) {
final konu = ders?.konular?.elementAt(j);
listkonular.add(konu?.konuBasligi ?? '');
// print(konu?.konuBasligi);
}
}
return listkonular;
}
Step4: Finally display the items in GridView using FutureBuilder<ReportData>
FutureBuilder<ReportData>(
future: DataFromReport.getDataLocally(context),
builder: (context, snapshot) {
final data = snapshot.data;
final List<String> list = getkonular(data);
return GridView.count(
crossAxisCount: 2,
padding: const EdgeInsets.only(
left: 12.0, right: 12.0, top: 8.0),
scrollDirection: Axis.vertical,
childAspectRatio: 1,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: List.generate(list.length, (index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
child: Center(
child: Text(list[index],
style: const TextStyle(
fontSize: 20,
color: Colors.white,
))));
}));
}),
SnapShot of the Example:
main.dart full code.
import 'package:flutter/material.dart';
import 'package:get_local_json_data/model.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test',
home: Scaffold(
appBar: AppBar(
title: const Text('Gridview From JSON'),
),
body: FutureBuilder<ReportData>(
future: DataFromReport.getDataLocally(context),
builder: (context, snapshot) {
final data = snapshot.data;
final List<String> list = getkonular(data);
return GridView.count(
crossAxisCount: 2,
padding: const EdgeInsets.only(
left: 12.0, right: 12.0, top: 8.0),
scrollDirection: Axis.vertical,
childAspectRatio: 1,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: List.generate(list.length, (index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
child: Center(
child: Text(list[index],
style: const TextStyle(
fontSize: 20,
color: Colors.white,
))));
}));
}),
));
}
}
//getting list of konular from ReportData
List<String> getkonular(ReportData? data) {
List<String> listkonular = [];
//konular is not present in all dersler
// so fist get the length of dersler
int length = data?.bende?.dersler?.length ?? 0;
for (var i = 0; i < length; i++) {
final ders = data?.bende?.dersler?.elementAt(i);
//now get the number of konular
int length2 = ders?.konular?.length ?? 0;
for (var j = 0; j < length2; j++) {
final konu = ders?.konular?.elementAt(j);
listkonular.add(konu?.konuBasligi ?? '');
// print(konu?.konuBasligi);
}
}
return listkonular;
}
class DataFromReport {
static Future<ReportData> getDataLocally(BuildContext context) async {
final assetBundle = DefaultAssetBundle.of(context);
final data = await assetBundle.loadString('data/veri.json');
final reportData = reportDataFromJson(data);
return reportData;
}
}
Folder Structure
Hope this will be helpful for you.
Actually you have to check for state before trying to use data in future builder. Try these -
FutureBuilder(
future: DefaultAssetBundle.of(context).loadString('data/veri.json'),
builder: (ctx, snapshot) {
// Checking if future is resolved
if (snapshot.connectionState == ConnectionState.done) {
// If we got an error
if (snapshot.hasError) {
return Center(
child: Text(
'${snapshot.error} occured',
style: TextStyle(fontSize: 18),
),
);
// if we got our data
} else if (snapshot.hasData) {
// Extracting data from snapshot object
var read = json.decode(snapshot.data.toString());
return GridView.count(
crossAxisCount: 2,
padding:
const EdgeInsets.only(left: 12.0, right: 12.0, top: 8.0),
scrollDirection: Axis.vertical,
childAspectRatio: 1,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
children: [
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
),
],
);
}
}
),
Hope it helps.
You have two options:
First Option: is to continue using GridView.count() and for the children you have to just iterate on them in any method, maybe for loop or .map() method.
Let's say you will display the dersler read from the JSON file and you have created a variable to point on them like the following:
var read = json.decode(snapshot.data.toString());
final List dersler = read['dersler'];
Now you can generate the children by iterating over the data,
Example using .map() method:
children: dersler.map((item) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
);
}).toList(),
Example using for loop:
children: [
for (int i = 0; i < dersler.length; i++)
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
)
],
Second Option (Suggested): is to use GridView.builder() instead of using GridView.count() which gives you a bonus of lazy-loading the data into memory, which means only the data that is currently visible on the screen would be held in the memory, which is a very good optimization made out of the box by Flutter.
Example:
FutureBuilder(
future: DefaultAssetBundle.of(context).loadString('data/veri.json'),
builder: (context, snapshot) {
var read = json.decode(snapshot.data.toString());
final List dersler = read['dersler'];
return GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
padding: const EdgeInsets.only(left: 12.0, right: 12.0, top: 8.0),
scrollDirection: Axis.vertical,
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: dersler.length,
itemBuilder: (BuildContext context, int index) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16)),
clipBehavior: Clip.antiAlias,
color: Colors.blue[200],
);
},
);
},
),
this is my first flutter JSON example, I tried to fetch data from the JSON link and display it on a drop-down list.
I am getting the response on the console but the drop-down list doesn't work
any help, please?......................................................................................................................................................................................................................................................................................................................
this is the body
ERROR
this is my code
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
_getfamilyList();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 15, right: 15, top: 5),
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton<String>(
value: _myfamily,
iconSize: 30,
icon: (null),
style: TextStyle(
color: Colors.black54,
fontSize: 16,
),
hint: Text('Select family'),
onChanged: (String newValue) {
setState(() {
_myfamily = newValue;
print(_myfamily);
});
},
items: familysList?.map((item) {
return new DropdownMenuItem(
child: new Text(item['firsName']),
);
})?.toList() ??
[],
),
),
),
),
],
),
),
],
),
);
}
List familysList;
String _myfamily;
String familyInfoUrl =
'http://10.0.2.2:3000/genocheck/user/getmembrefamille/f1';
Future<String> _getfamilyList() async {
await http.get(familyInfoUrl).then((response) {
var data = json.decode(response.body);
print(data);
setState(() {
familysList = data['famille'];
});
});
}
}
as I see the problem is in your JSON response
famille is the first element ,
the list of data is the second element
however in your code familysList = data['famille'];
you are assuming that famille is a key and the list of data is the value and this is not correct
so answer is one of those
1 - make your asignment like familysList = data[0];
2- change your json to be {"famille" :[{"id":8654,"firstname":"some name"]"}
The error caused because although data's type is List that can access by 'int' index, you access like Map.
data['famille']
As your data body, data[0] is 'famille' and data[1] is data what you want.
data[1] is
[
{
"_id": "",
"firstName": "",
}
]
You can copy paste run full code below
Step 1: data[0] is String famille, data[1] is List you want
familysList = data[1];
Step 2: firsName is typo you need firstName
Step 3: DropdownMenuItem need value attribute
items: familysList?.map((item) {
return DropdownMenuItem<String>(
child: Text("${item["firstName"]}"),
value: item["firstName"],
);
})?.toList() ??
working demo
full code
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
_getfamilyList();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 15, right: 15, top: 5),
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton<String>(
value: _myfamily,
iconSize: 30,
icon: (null),
style: TextStyle(
color: Colors.black54,
fontSize: 16,
),
hint: Text('Select family'),
onChanged: (String Value) {
setState(() {
_myfamily = Value;
print("_myfamily $_myfamily");
});
},
items: familysList?.map((item) {
//print(item["firstName"]);
return DropdownMenuItem<String>(
child: Text("${item["firstName"]}"),
value: item["firstName"],
);
})?.toList() ??
[],
),
),
),
),
],
),
),
],
),
);
}
List familysList;
String _myfamily;
String familyInfoUrl =
'http://10.0.2.2:3000/genocheck/user/getmembrefamille/f1';
Future<String> _getfamilyList() async {
String jsonString = '''
[
"famille",
[
{
"_id" : "123",
"firstName":"abc"
},
{
"_id" : "456",
"firstName":"def"
}
]
]
''';
http.Response response = http.Response(jsonString, 200);
var data = json.decode(response.body);
print(data);
setState(() {
familysList = data[1];
});
/*await http.get(familyInfoUrl).then((response) {
var data = json.decode(response.body);
print(data);
setState(() {
familysList = data[1];
});
});*/
}
}
full code 2 for new question
import 'package:flutter/material.dart';
import 'dart:convert';
import 'package:http/http.dart' as http;
class UserElement {
UserElement({
this.id,
this.firstName,
});
String id;
String firstName;
factory UserElement.fromJson(Map<String, dynamic> json) => UserElement(
id: json["_id"] == null ? null : json["_id"],
firstName: json["firstName"] == null ? null : json["firstName"],
);
Map<String, dynamic> toJson() => {
"_id": id == null ? null : id,
"firstName": firstName == null ? null : firstName,
};
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
_getfamilyList();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.only(left: 15, right: 15, top: 5),
color: Colors.white,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Expanded(
child: DropdownButtonHideUnderline(
child: ButtonTheme(
alignedDropdown: true,
child: DropdownButton<UserElement>(
value: _myfamily,
iconSize: 30,
icon: (null),
style: TextStyle(
color: Colors.black54,
fontSize: 16,
),
hint: Text('Select family'),
onChanged: (UserElement Value) {
setState(() {
_myfamily = Value;
print("_myfamily ${_myfamily.firstName}");
});
},
items: familysList?.map((item) {
return DropdownMenuItem<UserElement>(
child: Text("${item.id} ${item.firstName}"),
value: item,
);
})?.toList() ??
[],
),
),
),
),
],
),
),
],
),
);
}
List<UserElement> familysList = [];
UserElement _myfamily;
String familyInfoUrl =
'http://10.0.2.2:3000/genocheck/user/getmembrefamille/f1';
Future<String> _getfamilyList() async {
String jsonString = '''
[
"famille",
[
{
"_id" : "123",
"firstName":"abc"
},
{
"_id" : "456",
"firstName":"abc"
}
]
]
''';
http.Response response = http.Response(jsonString, 200);
var data = json.decode(response.body);
//print(data);
setState(() {
List<dynamic> listData = data[1];
for (var i = 0; i < listData.length; i++) {
familysList.add(UserElement.fromJson(listData[i]));
}
});
/*await http.get(familyInfoUrl).then((response) {
var data = json.decode(response.body);
print(data);
setState(() {
familysList = data['famille'];
});
});*/
}
}
I have logged in from an Api of login. Then i got a response data of json. I need to show that json data in a list view. and need to show the array count in notification icon for counting it. How can i do it ? please help.
The response json format is -
{
"id": 1,
"name": "Mr Admin",
"email": "admin2#gmail.com",
"username": "admin2",
"api_token": "oYfajebhRzlxpMZV8dHI6w5R8CrpgybaGqX2ZaIXkGpumE9hZSgLVVINAgaF",
"user_types_id": null,
"created_at": "2020-01-21 16:21:48",
"updated_at": "2020-10-14 11:31:10",
"deleted_at": null,
"unread_notifications": [
{
"id": "d54ee0cc-054a-4d51-a53b-5f6f658841ae",
"type": "App\\Notifications\\HandSlipStatusNotification",
"notifiable_id": 1,
"notifiable_type": "App\\User",
"data": {
"payment_id": 471,
"generate_payment_id": "10200471",
"message": "Hand Slip Settled.",
"amount": 850
},
"read_at": null,
"created_at": "2020-10-12 15:50:38",
"updated_at": "2020-10-12 15:50:38"
},
{
"id": "aedb7880-4201-4805-b017-62242dfed741",
"type": "App\\Notifications\\HandSlipStatusNotification",
"notifiable_id": 1,
"notifiable_type": "App\\User",
"data": {
"payment_id": 471,
"generate_payment_id": "10200471",
"message": "Hand Slip Disbursed.",
"amount": 850
},
"read_at": null,
"created_at": "2020-10-12 15:50:25",
"updated_at": "2020-10-12 15:50:25"
},
i can show the id , name , email etc but cann't access unread_notifications.
my code -
api_service.dart ->
class LoginResponseModel {
final String token;
final String error;
LoginResponseModel({this.token, this.error});
factory LoginResponseModel.fromJson(Map<String, dynamic> json) {
return LoginResponseModel(
token: json["token"] != null ? json["token"] : "",
error: json["error"] != null ? json["error"] : "",
);
}
}
class LoginRequestModel {
String email;
String password;
String username;
LoginRequestModel({
this.email,
this.password,
this.username,
});
Map<String, dynamic> toJson() {
Map<String, dynamic> map = {
// 'email': email.trim(),
'username': username.trim(),
'password': password.trim(),
};
return map;
}
}
login_model
class LoginResponseModel {
final String token;
final String error;
LoginResponseModel({this.token, this.error});
factory LoginResponseModel.fromJson(Map<String, dynamic> json) {
return LoginResponseModel(
token: json["token"] != null ? json["token"] : "",
error: json["error"] != null ? json["error"] : "",
);
}
}
class LoginRequestModel {
String email;
String password;
String username;
LoginRequestModel({
this.email,
this.password,
this.username,
});
Map<String, dynamic> toJson() {
Map<String, dynamic> map = {
// 'email': email.trim(),
'username': username.trim(),
'password': password.trim(),
};
return map;
}
}
login.dart
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'homepage.dart';
class Login extends StatefulWidget {
#override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
var allData ;
TextEditingController _userController = TextEditingController();
TextEditingController _passwordController = TextEditingController();
bool _isLoading = false;
// arrange method for api log in
signIn( String username,String password) async {
// String url = "https://reqres.in/api/login";
String url = "my url";
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
Map body = { "username": username, "password": password
};
var notificatiion;
var jsonResponse;
var res = await http.post(url, body: body);
//need to check the api status
if (res.statusCode == 200) {
jsonResponse = json.decode(res.body);
notificatiion = jsonResponse['unread_notifications'];
print("Response status: ${res.statusCode}");
print("Response status: ${res.body}");
if (jsonResponse != null) {
setState(() {
_isLoading = false;
});
sharedPreferences.setString("token", jsonResponse['token']);
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (BuildContext) =>
HomePage(
email: jsonResponse['email'],
name: jsonResponse['name'],
username : jsonResponse['username'],
notification: notificatiion,
),
),
(Route<dynamic> route) => false);
}
} else {
setState(() {
_isLoading == false;
});
print(" Response status : ${res.body}");
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SingleChildScrollView(
child: Center(
child: Container(
padding: EdgeInsets.fromLTRB(20, 100, 20, 20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text("Login",
style: TextStyle(fontSize: 32),
),
SizedBox(
height: 30,
),
Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Container(
height: 220,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(30),
child: TextField(
controller: _userController,
decoration: InputDecoration(hintText: "username"),
),
),
Padding(
padding: const EdgeInsets.all(30),
child: TextField(
controller: _passwordController,
obscureText: true,
decoration: InputDecoration(hintText: "Password"),
),
),
],
),
),
),
SizedBox(
height: 60,
width: MediaQuery.of(context).size.width,
child: RaisedButton(
color: Colors.lightBlue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
child: Text("Sign In"),
onPressed: _userController.text == ""||
_passwordController.text == ""
? null
: () {
setState(() {
_isLoading = true ;
});
signIn(_userController.text, _passwordController.text);
},
),
),
SizedBox(
height: 20,
),
FlatButton(
child: Text("Forgot password"),
onPressed: (){
},
),
],
),
),
),
),
),
);
}
}
I want to show all the response value in home page .In notification's icon i want to show array count.
homepage.dart
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'login.dart';
import 'login.dart';
class HomePage extends StatelessWidget {
String email;
String name;
String username;
List<dynamic> notification;
HomePage({this.email, this.name, this.username, this.notification, });
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Cash-Management"),
backgroundColor: Colors.blue,
actions: [
IconButton(icon: Icon(Icons.notifications), onPressed: () {}),
IconButton(
icon: Icon(Icons.exit_to_app),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Login()),
);
}),
],
),
body: ListView(
children: <Widget>[
Container(
height: 200,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
" $email ",
style: TextStyle(fontSize: 16),
),
Text(" $name "),
Text(" $username "),
],
),
),
Container(
height: 300,
child: ListView.builder(
itemCount: notification == null ? 0 : notification.length,
itemBuilder: (context, index){
return ListTile(
title: Text(notification[index] ["id"]),
subtitle: Text(notification[index]["type"]),
);
}),
),
],
),
),
);
}
}