Related
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
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 created a PickImages class which can takes images both from camera and gallery like below. Now I want to post the images as base64 string to a json api server.
Here is PickImages class.
import 'dart:convert';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
//import 'services/services.dart';
class PickImages extends StatefulWidget {
#override
_PickImagesState createState() => _PickImagesState();
}
class _PickImagesState extends State<PickImages> {
List<Object> images = List<Object>();
Future<File> _imageFile;
bool _isVisible = false;
Future _onAddImageClick(int index, int type) async {
if (images != null)
setState(() {
// ignore: deprecated_member_use
_imageFile = ImagePicker.pickImage(
source: type == 1 ? ImageSource.camera : ImageSource.gallery,
imageQuality: 50,
);
getFileImage(index);
});
}
void getFileImage(int index) async {
_imageFile.then((file) async {
setState(() {
ImageUploadModel imageUpload = new ImageUploadModel();
imageUpload.imageFile = file;
images.replaceRange(index, index + 1, [imageUpload]);
});
});
}
void showImageBox() {
setState(() {
_isVisible = !_isVisible;
});
}
#override
void initState() {
super.initState();
setState(() {
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Post Images'),
),
body: Column(
children: <Widget>[
Container(
//padding: EdgeInsets.only(right: 5),
child: Card(
elevation: 5,
child: ListTile(
trailing: Icon(Icons.attachment),
title: Text('Attachments'),
onTap: () {
showImageBox();
},
),
),
),
Visibility(
visible: _isVisible,
child: Padding(
padding: const EdgeInsets.only(top: 5.0, right: 5.0),
child: GridView.count(
shrinkWrap: true,
crossAxisCount: 3,
childAspectRatio: 1,
children: List.generate(images.length, (index) {
if (images[index] is ImageUploadModel) {
ImageUploadModel uploadModel = images[index];
//base64 image
List<int> imageBytes =
uploadModel.imageFile.readAsBytesSync();
String base64Image = base64Encode(
imageBytes); //'base64Image' holds the base64 image string
return Card(
clipBehavior: Clip.antiAlias,
child: Stack(
children: <Widget>[
Image.file(
uploadModel.imageFile,
fit: BoxFit.cover,
width: 300,
height: 300,
),
Positioned(
right: 5,
top: 5,
child: InkWell(
child: Icon(
Icons.remove_circle,
size: 20,
color: Colors.red,
),
onTap: () {
setState(() {
images.replaceRange(
index, index + 1, ['Add Image']);
});
},
),
),
RaisedButton(
child: Text('imgInfo'),
onPressed: () {
print(
"${uploadModel.imageFile.lengthSync() / 1024} KB"); //print image size in kb
print(uploadModel
.imageFile.path); //print image path
log(base64Image);
},
),
],
),
);
} else {
return Card(
child: IconButton(
icon: Icon(Icons.camera_alt),
onPressed: () {
showModalBottomSheet(
context: context,
builder: (BuildContext context) {
return SafeArea(
child: Container(
child: new Wrap(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.photo_camera),
title: new Text('Camera'),
onTap: () {
_onAddImageClick(index, 1);
Navigator.of(context).pop();
},
),
new ListTile(
leading:
new Icon(Icons.photo_library),
title: new Text('Gallery'),
onTap: () {
_onAddImageClick(index, 2);
Navigator.of(context).pop();
}),
],
),
),
);
},
);
},
),
);
}
}),
),
),
),
RaisedButton(
child: Text('send'),
onPressed: () {
//postImage(base64Image);
},
),
],
),
);
}
}
class ImageUploadModel {
File imageFile;
ImageUploadModel({
this.imageFile,
});
}
Here is ImageModel.
class ImageModel {
String attachment;
ImageModel({this.attachment});
ImageModel.fromJson(Map<String, dynamic> json) {
attachment = json['Attachment'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['Attachment'] = this.attachment;
return data;
}
}
Here is services.dart where in "Attatchment" : " " I have to sent the base64 images string.
import 'dart:convert';
import 'dart:async';
import 'package:http/http.dart' as http;
import 'package:post_image/model/model.dart';
Future<ImageModel> postImage() async {
Map data = {
"Attachment": ""
};
var body = json.encode(data);
final http.Response response = await http.post(
'url',
body: body,
);
print(response.body);
print(body);
if (response.statusCode == 200) {
return ImageModel.fromJson(
jsonDecode(response.body),
);
} else {
throw Exception('Failed to send');
}
}
You can follow this guide on sending data in Flutter using http.post(). To send a List<ImageModel>, you just need to encode it using json.encode() when passing it in the body of your http.post request.
I'm try ti create a list from a json but it throws me the error: "List is not subtype of type Map<string, dynamic>".
The first part of code is where I am trying to create the list bwhich is in a widget that is called to the main widget.On the second block of code is where I do the fetch and recives an endpoint and then returns the response back and the last one is the structure of the json.
import 'package:flutter/material.dart';
import 'package:eshop/models/products.dart';
import 'package:eshop/function/fetch.dart';
const endPoint = 'https://sistemas.cruzperez.com/flutter/jsonPrueba.json';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Future<Product> futureProduct;
#override
void initState() {
super.initState();
futureProduct = getData(endPoint);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar:AppBar(
title: Text('Eshop'),
automaticallyImplyLeading: false,
actions: <Widget>[
IconButton(icon: Icon(Icons.shopping_cart, color: Colors.white), onPressed: (){})
],
),
body: Center(
child: Container(
child: Column(
children: <Widget>[
listJson(futureProduct)
],
),
)
),
);
}
}
Widget listJson(futureProduct){
return Container(
child: FutureBuilder<Product>(
future: futureProduct,
builder: (context, snapshot){
if(snapshot.hasData){
return Text(snapshot.data.nombre);
}else if(snapshot.hasError){
return Text("${snapshot.error}");
}
return CircularProgressIndicator();
},
),
);
}
import 'dart:async';
import 'package:http/http.dart' as http;
import 'package:eshop/models/products.dart';
Future<Product> getData(endPoint) async{
final response = await http.get(endPoint);
if (response.statusCode == 200) {
return Product.fromJson(json.decode(response.body));
}else{
throw Exception('Error a cargar json');
}
}
class Product{
final int idSucursal;
final int idProducto;
final String nombre;
final String categoria;
final int precio;
final int disponible;
final String descripcion;
final String imgUrl;
Product({
this.idSucursal,
this.idProducto,
this.nombre,
this.categoria,
this.precio,
this.disponible,
this.descripcion,
this.imgUrl
});
factory Product.fromJson(Map<String, dynamic> json){
return Product(
idSucursal: json['id_sucursal'],
idProducto: json['id_producto'],
nombre: json['nombre'],
categoria: json['categoria'],
precio: json['precio'],
disponible: json['disponible'],
descripcion: json['descripcion'],
imgUrl: json['img_url'],
);
}
}
You can copy paste run full code below
Step 1: You need to use List<Product> and parse with productFromJson
List<Product> productFromJson(String str) =>
List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));
Step 2: You can display data with ListView
return ListView.builder(
shrinkWrap: true,
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].nombre.toString()),
],
),
));
working demo
full code
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
List<Product> productFromJson(String str) =>
List<Product>.from(json.decode(str).map((x) => Product.fromJson(x)));
String productToJson(List<Product> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class Product {
Product({
this.idSucrsal,
this.idProducto,
this.nombre,
this.categoria,
this.precio,
this.disponible,
this.descripcion,
this.imgUrl,
});
int idSucrsal;
int idProducto;
String nombre;
Categoria categoria;
int precio;
int disponible;
String descripcion;
String imgUrl;
factory Product.fromJson(Map<String, dynamic> json) => Product(
idSucrsal: json["id_sucrsal"],
idProducto: json["id_producto"],
nombre: json["nombre"],
categoria: categoriaValues.map[json["categoria"]],
precio: json["precio"],
disponible: json["disponible"],
descripcion: json["descripcion"],
imgUrl: json["img_url"],
);
Map<String, dynamic> toJson() => {
"id_sucrsal": idSucrsal,
"id_producto": idProducto,
"nombre": nombre,
"categoria": categoriaValues.reverse[categoria],
"precio": precio,
"disponible": disponible,
"descripcion": descripcion,
"img_url": imgUrl,
};
}
enum Categoria { RES, CERDO, EMBUTIDO }
final categoriaValues = EnumValues({
"cerdo": Categoria.CERDO,
"embutido": Categoria.EMBUTIDO,
"res": Categoria.RES
});
class EnumValues<T> {
Map<String, T> map;
Map<T, String> reverseMap;
EnumValues(this.map);
Map<T, String> get reverse {
if (reverseMap == null) {
reverseMap = map.map((k, v) => new MapEntry(v, k));
}
return reverseMap;
}
}
const endPoint = 'https://sistemas.cruzperez.com/flutter/jsonPrueba.json';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Future<List<Product>> futureProduct;
Future<List<Product>> getData(endPoint) async {
final response = await http.get(endPoint);
if (response.statusCode == 200) {
return productFromJson(response.body);
} else {
throw Exception('Error a cargar json');
}
}
#override
void initState() {
super.initState();
futureProduct = getData(endPoint);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Eshop'),
automaticallyImplyLeading: false,
actions: <Widget>[
IconButton(
icon: Icon(Icons.shopping_cart, color: Colors.white),
onPressed: () {})
],
),
body: Center(
child: Container(
child: Column(
children: <Widget>[Expanded(child: listJson(futureProduct))],
),
)),
);
}
}
Widget listJson(futureProduct) {
return Container(
child: FutureBuilder<List<Product>>(
future: futureProduct,
builder: (context, AsyncSnapshot<List<Product>> 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(
shrinkWrap: true,
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].nombre.toString()),
],
),
));
});
}
}
},
),
);
}
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: HomePage(),
);
}
}
I have the following code
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter_form_builder/flutter_form_builder.dart';
class MyData {
String title;
String days;
String words;
String rep;
String gender;
var username;
MyData({this.gender, this.title, this.days, this.words, this.rep, this.username,
});
}
class StepperBody extends StatefulWidget {
#override
_StepperBodyState createState() => _StepperBodyState();
}
class _StepperBodyState extends State<StepperBody> {
int currStep = 0;
static var _focusNode = FocusNode();
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
Future<List<String>> _future;
Future<List<String>> _car;
List<GlobalKey<FormState>> formKeys = [
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>()
];
String _key = "786465659081B207EB5BF1EF9AF7552A6";
String _api = "https://10.0.2.2/api/";
Future<void> senddata(List<String> username) async {
final response = await http.post(
_api + "insert_data.php?key=" + _key, body: {
"username": username,
});
var resp = jsonDecode(response.body);
print(resp.toString());
}
Future<List<String>> getData() async {
var url = _api + "get_data.php?key=" + _key;
http.Response response = await http.get(url);
var resp = jsonDecode(response.body);
print(resp.toString());
return resp.map<String>((m) => m['username'] as String).toList();
}
Future<List<String>> getCar() async {
var url = _api + "get_car.php?key=" + _key;
http.Response response = await http.get(url);
var resp = jsonDecode(response.body);
print(resp.toString());
return resp.map<String>((m) => m['plate'] as String).toList();
}
#override
void initState() {
super.initState();
_future = getData();
_car = getCar();
_focusNode.addListener(() {
setState(() {});
print('Has focus: $_focusNode.hasFocus');
});
}
#override
Widget build(BuildContext context) {
void showSnackBarMessage(String message,
[MaterialColor color = Colors.red]) {
Scaffold.of(context).showSnackBar(SnackBar(content: Text(message)));
}
void _submitDetails(List<String> username) {
final FormState formState = _formKey.currentState;
final FormBuilderState fbKeyState = _fbKey.currentState;
/*
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
print(_fbKey.currentState.value);
}
*/
if (!fbKeyState.validate()) {
showSnackBarMessage('Please enter correct data');
senddata(username);
} else {
showSnackBarMessage('Saved');
formState.save();
senddata(username);
print("Name: $username");
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
print(_fbKey.currentState.value);
}
}
}
return FutureBuilder<List<String>>(
future: Future.wait([_future, _car]),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
final steps = [
Step(
title: const Text('Users'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[0],
child: Column(
children: <Widget>[
FormBuilder(
key: _fbKey,
autovalidate: true,
child: FormBuilderCheckboxList(
decoration:
InputDecoration(labelText: "Languages you know"),
attribute: "languages",
initialValue: ["English"],
options: snapshot.data[0]
.map((languages) => FormBuilderFieldOption(
value: languages, child: Text("$languages")))
.toList(),
),
),
],
),
),
),
Step(
title: const Text('Users'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[1],
child: Column(
children: <Widget>[
FormBuilder(
key: _fbKey,
autovalidate: true,
child: FormBuilderCheckboxList(
decoration:
InputDecoration(labelText: "Cars"),
attribute: "cars",
initialValue: ["BM-WD01"],
options: snapshot.data[1]
.map((car) => FormBuilderFieldOption(
value: car, child: Text("$car")))
.toList(),
),
),
],
),
),
),
];
return Container(
child: Form(
key: _formKey,
child: ListView(children: <Widget>[
Stepper(
steps: steps,
physics: ClampingScrollPhysics(),
type: StepperType.vertical,
currentStep: this.currStep,
onStepContinue: () {
setState(() {
if (formKeys[currStep].currentState.validate()) {
if (currStep < steps.length - 1) {
currStep = currStep + 1;
} else {
currStep = 0;
}
}
// else {
// Scaffold
// .of(context)
// .showSnackBar( SnackBar(content: Text('$currStep')));
// if (currStep == 1) {
// print('First Step');
// print('object' + FocusScope.of(context).toStringDeep());
// }
// }
});
},
controlsBuilder: (BuildContext context,
{VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
//
RaisedButton(
color: Colors.red,
child: Text("Forward",
style: TextStyle(color: Colors.white)),
onPressed: onStepContinue,
),
SizedBox(width: 15,),
RaisedButton(
color: Colors.red,
child: Text(
"Back", style: TextStyle(color: Colors.white)),
onPressed: onStepCancel,
),
],
);
},
onStepCancel: () {
setState(() {
if (currStep > 0) {
currStep = currStep - 1;
} else {
currStep = 0;
}
});
},
onStepTapped: (step) {
setState(() {
currStep = step;
});
},
),
RaisedButton(
child: Text(
'Save',
style: TextStyle(color: Colors.white),
),
onPressed: () {
var submitDetails = _submitDetails;
submitDetails(snapshot.data);
},
color: Colors.lightGreen,
),
]),
));
} else {
return CircularProgressIndicator();
}
}
);
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: "test",),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
MyAppScreenMode createState() => MyAppScreenMode();
}
class MyAppScreenMode extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.red,
),
home: new Scaffold(
appBar: new AppBar(
title: new Text('Test stepper'),
),
body: new StepperBody(),
));
}
}
I want to display multiple lists from mySQL, the first function _future works fine, but when I replace future: _future to
future: Future.wait([_future, _car]),
I get an
The element type 'Future<List>' can't be assigned to the list
type 'Future'
I have tried lots of other solutions but none of them works to use snapshot.data[0], snapshot.data1 and so on for more queries and data to display from different tables.
Can't get to work with more futurebuilders which would be even easier for each step own, but then I get
Step(
title: const Text('Users'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[0],
child: FutureBuilder<List>(
future: _future,
// ignore: missing_return
builder: (BuildContext context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
Column(
children: <Widget>[
FormBuilder(
key: _fbKey,
autovalidate: true,
child: FormBuilderCheckboxList(
decoration:
InputDecoration(
labelText: "Languages you know"),
attribute: "languages",
initialValue: ["English"],
options: snapshot.data
.map((gender) =>
FormBuilderFieldOption(
value: gender, child: Text("$gender")))
.toList(),
),
),
],
);
}
}
),
),
),
];
Any help would be appreciated.
The working solution for the question. If there is any better way feel free to post :)
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:flutter_form_builder/flutter_form_builder.dart';
class MyData {
String title;
String days;
String words;
String rep;
String gender;
var username;
MyData(
{this.gender, this.title, this.days, this.words, this.rep, this.username,
});
}
class StepperBody extends StatefulWidget {
#override
_StepperBodyState createState() => _StepperBodyState();
}
class _StepperBodyState extends State<StepperBody> {
int currStep = 0;
static var _focusNode = FocusNode();
GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final GlobalKey<FormBuilderState> _fbKey = GlobalKey<FormBuilderState>();
Future<List<String>> _future;
Future<List<String>> _getcar;
List<GlobalKey<FormState>> formKeys = [
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>(),
GlobalKey<FormState>()
];
String _key = "786465659081B207EB5BF1EF9AF7552A6";
String _api = "https://10.0.2.2/api/";
Future<void> senddata() async {
final response = await http.post(
_api + "insert_data.php?key=" + _key, body: {
});
var resp = jsonDecode(response.body);
print(resp.toString());
}
Future<List<String>> getData() async {
var url = _api + "get_data.php?key=" + _key;
http.Response response = await http.get(url);
var resp = jsonDecode(response.body);
print(resp.toString());
return resp.map<String>((m) => m['username'] as String).toList();
}
Future<List<String>> getCar() async {
var url = _api + "get_car.php?key=" + _key;
http.Response response = await http.get(url);
var resp = jsonDecode(response.body);
print(resp.toString());
return resp.map<String>((m) => m['plate'] as String).toList();
}
Widget getdis2(BuildContext context) {
return FutureBuilder<List<String>>(
future: _getcar, // a previously-obtained Future<String> or null
builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
List<Widget> children;
if (snapshot.hasData) {
children = <Widget>[
FormBuilderCheckboxList(
decoration:
InputDecoration(
labelText: "Languages you know"),
attribute: "languages",
initialValue: ["English"],
options: snapshot.data
.map((gender) =>
FormBuilderFieldOption(
value: gender, child: Text("$gender")))
.toList(),
),
];
} else if (snapshot.hasError) {
children = <Widget>[
Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'),
)
];
} else {
children = <Widget>[
SizedBox(
child: CircularProgressIndicator(),
width: 60,
height: 60,
),
const Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting result...'),
)
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: children,
),
);
},
);
}
Widget getdis(BuildContext context) {
return FutureBuilder<List<String>>(
future: _future, // a previously-obtained Future<String> or null
builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
List<Widget> children;
if (snapshot.hasData) {
children = <Widget>[
FormBuilderCheckboxList(
decoration:
InputDecoration(
labelText: "Languages you know"),
attribute: "languages",
initialValue: ["English"],
options: snapshot.data
.map((gender) =>
FormBuilderFieldOption(
value: gender, child: Text("$gender")))
.toList(),
),
];
} else if (snapshot.hasError) {
children = <Widget>[
Icon(
Icons.error_outline,
color: Colors.red,
size: 60,
),
Padding(
padding: const EdgeInsets.only(top: 16),
child: Text('Error: ${snapshot.error}'),
)
];
} else {
children = <Widget>[
SizedBox(
child: CircularProgressIndicator(),
width: 60,
height: 60,
),
const Padding(
padding: EdgeInsets.only(top: 16),
child: Text('Awaiting result...'),
)
];
}
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: children,
),
);
},
);
}
#override
void initState() {
super.initState();
_future = getData();
_getcar = getCar();
_focusNode.addListener(() {
setState(() {});
print('Has focus: $_focusNode.hasFocus');
});
}
#override
Widget build(BuildContext context) {
void showSnackBarMessage(String message,
[MaterialColor color = Colors.red]) {
Scaffold.of(context).showSnackBar(SnackBar(content: Text(message)));
}
void _submitDetails() {
final FormState formState = _formKey.currentState;
final FormBuilderState fbKeyState = _fbKey.currentState;
/*
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
print(_fbKey.currentState.value);
}
*/
if (!fbKeyState.validate()) {
showSnackBarMessage('Please enter correct data');
senddata();
} else {
showSnackBarMessage('Saved');
formState.save();
senddata();
print("Name: ");
_fbKey.currentState.save();
if (_fbKey.currentState.validate()) {
print(_fbKey.currentState.value);
}
}
}
final steps = [
Step(
title: const Text('Users'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[0],
child: getdis(context),
),
),
Step(
title: const Text('Cars'),
//subtitle: const Text('Subtitle'),
isActive: true,
//state: StepState.editing,
state: StepState.indexed,
content: Form(
key: formKeys[1],
child: getdis2(context),
),
),
];
return Container(
child: Form(
key: _formKey,
child: ListView(children: <Widget>[
Stepper(
steps: steps,
physics: ClampingScrollPhysics(),
type: StepperType.vertical,
currentStep: this.currStep,
onStepContinue: () {
setState(() {
if (formKeys[currStep].currentState.validate()) {
if (currStep < steps.length - 1) {
currStep = currStep + 1;
} else {
currStep = 0;
}
}
// else {
// Scaffold
// .of(context)
// .showSnackBar( SnackBar(content: Text('$currStep')));
// if (currStep == 1) {
// print('First Step');
// print('object' + FocusScope.of(context).toStringDeep());
// }
// }
});
},
controlsBuilder: (BuildContext context,
{VoidCallback onStepContinue, VoidCallback onStepCancel}) {
return Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
//
RaisedButton(
color: Colors.red,
child: Text("Forward",
style: TextStyle(color: Colors.white)),
onPressed: onStepContinue,
),
SizedBox(width: 15,),
RaisedButton(
color: Colors.red,
child: Text(
"Back", style: TextStyle(color: Colors.white)),
onPressed: onStepCancel,
),
],
);
},
onStepCancel: () {
setState(() {
if (currStep > 0) {
currStep = currStep - 1;
} else {
currStep = 0;
}
});
},
onStepTapped: (step) {
setState(() {
currStep = step;
});
},
),
RaisedButton(
child: Text(
'Save',
style: TextStyle(color: Colors.white),
),
onPressed: () {
var submitDetails = _submitDetails;
submitDetails();
},
color: Colors.lightGreen,
),
]),
));
}
}
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: "test",),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
MyAppScreenMode createState() => MyAppScreenMode();
}
class MyAppScreenMode extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.red,
),
home: new Scaffold(
appBar: new AppBar(
title: new Text('Test stepper'),
),
body: new StepperBody(),
));
}
}
Im not sure about this, but in my understanding, a FutureBuilder expects exactly 1 future. the returned value of this future is accessable with "snapshot.data".
If you need to wait for multiple futures to resolve, I propose you use multiple FutureBuilders.
Another way would be to use Future.wait() somewhere else and return all required data as one Furure from there.