Listing Data from API with Flutter - flutter

I can pull my data but not mirror it. The examples on the internet have always been used to reflect a single data. The data I have is multiple data. I want to reflect the data of different countries as a list.
I used Listview.builder and ListTile but it didn't work. I keep getting different errors. I couldn't find an up-to-date and working example. Could you help?
I have an API.
API URL: https://covid19-mohfw.herokuapp.com/
I converted this data as a model.
My Model:
class CovidModel {
List<States>? states;
Totals? totals;
CovidModel({this.states, this.totals});
CovidModel.fromJson(Map<String, dynamic> json) {
if (json['states'] != null) {
states = <States>[];
json['states'].forEach((v) {
states!.add(new States.fromJson(v));
});
}
totals =
json['totals'] != null ? new Totals.fromJson(json['totals']) : null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.states != null) {
data['states'] = this.states!.map((v) => v.toJson()).toList();
}
if (this.totals != null) {
data['totals'] = this.totals!.toJson();
}
return data;
}
}
class States {
String? state;
int? cases;
int? recoveries;
int? deaths;
int? total;
States({this.state, this.cases, this.recoveries, this.deaths, this.total});
States.fromJson(Map<String, dynamic> json) {
state = json['state'];
cases = json['cases'];
recoveries = json['recoveries'];
deaths = json['deaths'];
total = json['total'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['state'] = this.state;
data['cases'] = this.cases;
data['recoveries'] = this.recoveries;
data['deaths'] = this.deaths;
data['total'] = this.total;
return data;
}
}
class Totals {
int? cases;
int? recoveries;
int? deaths;
int? total;
Totals({this.cases, this.recoveries, this.deaths, this.total});
Totals.fromJson(Map<String, dynamic> json) {
cases = json['cases'];
recoveries = json['recoveries'];
deaths = json['deaths'];
total = json['total'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['cases'] = this.cases;
data['recoveries'] = this.recoveries;
data['deaths'] = this.deaths;
data['total'] = this.total;
return data;
}
}
and my fetchCountry file from which I Pulled Data
import 'dart:convert';
import 'package:covidapp/models/covidModel.dart';
import 'package:http/http.dart' as http;
class FetchCountry {
Future<CovidModel> fetchData() async {
final response =
await http.get(Uri.parse("https://covid19-mohfw.herokuapp.com/"));
if (response.statusCode == 200) {
final result = CovidModel.fromJson(jsonDecode(response.body));
return result;
} else {
throw Exception('Error');
}
}
}
Finally, the part where I try to reflect the data:
import 'package:covidapp/models/covidModel.dart';
import 'package:flutter/material.dart';
import 'package:covidapp/services/fetchCountry.dart';
class covidPage extends StatefulWidget {
const covidPage({Key? key}) : super(key: key);
#override
State<covidPage> createState() => _covidPageState();
}
class _covidPageState extends State<covidPage> {
late Future<CovidModel> futureCountry = FetchCountry().fetchData();
#override
void initState() {
super.initState();
futureCountry = FetchCountry().fetchData();
}
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
width: double.infinity,
height: double.infinity,
color: Color.fromRGBO(255, 246, 234, 1),
child: Column(children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.03,
),
const Text(
'Covid Data',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 29,
fontWeight: FontWeight.w700,
color: Color.fromARGB(255, 112, 108, 112)),
),
]),
)),
);
}
}

Store all your data in model instead of future model will work
class _covidPageState extends State<covidPage> {
late CovidModel? futureCountry;
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
futureCountry = await FetchCountry().fetchData();
print(futureCountry?.states?.length); // You can access all data with futureCountry?.
setState(() {});
});
}
/// your code

You can use a FutureBuilder like this:
FutureBuilder(
future: futureCountry,
builder: (context, snap) {
if (snap.connectionState == ConnectionState.waiting) {
return CupertinoActivityIndicator();
}
if (snap.hasError) {
return Text("Error!");
}
final data =
snap.data as CovidModel;
return ListView.builder(
shrinkWrap: true,
padding: EdgeInsets.symmetric(vertical: 20),
physics: const AlwaysScrollableScrollPhysics(),
itemCount: data.states.length,
itemBuilder: (c, index) => CovidDetailWidget(data[index]),
);
},
)

Use the Below code to show data in List view
import 'package:flutter/material.dart';
import 'package:link/deep_link.dart';
class covidPage extends StatefulWidget {
const covidPage({Key? key}) : super(key: key);
#override
State<covidPage> createState() => _covidPageState();
}
class _covidPageState extends State<covidPage> {
late CovidModel? futureCountry = null;
#override
void initState() {
super.initState();
_getData();
}
void _getData() async {
futureCountry = (await FetchCountry().fetchData());
Future.delayed(const Duration(seconds: 1)).then((value) => setState(()
{}));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('REST API Example'),
),
body: futureCountry?.states == null || futureCountry?.states?.length == 0
? const Center(
child: CircularProgressIndicator(),
)
: ListView.builder(
itemCount: futureCountry?.states?.length,
itemBuilder: (context, index) {
return Card(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Text(futureCountry?.states![index].state ?? ''),
],
),
],
),
);
},
),
);
}
}

Related

How to fetch data API to dropdown

how do I call the API data into the dropdown I have done several times, when I used local data in the form of a String list I managed to call the data, but when I tried to call from the API data the result was empty and the results in the dropdown did not display any data
Future<List<Agama>> getAgama() async {
String url = Constant.baseURL;
String token = await UtilSharedPreferences.getToken();
final response = await http.get(
Uri.parse(
'$url/auth/mhs_siakad/dosen',
),
headers: {
'Authorization': 'Bearer $token',
},
);
print(response.statusCode);
print(response.body);
if (response.statusCode == 200) {
final result =
json.decode(response.body)['nm_agama'] as Map<String, dynamic>;
UserBiodata agama = UserBiodata.fromJson(result);
List<Agama> l = agama.data ?? [];
return l;
} else {
throw Exception();
}
}
in widget
List<Agama>? religion = [];
#override
void initState() {
super.initState();
BiodataProvider().getAgama();
}
var dropdownAgama;
...
FutureBuilder(
future: BiodataProvider().getBiodata(),
builder: (context, snapshot) {
if (snapshot.hasData) {
print(' ini Agama $religion');
return Column(
children: [
Text(
snapshot.data!.data!.name.toString(),
style: bold5,
),
DropdownButton(
hint: const Text('Religion'),
items: religion!.map((item) {
return DropdownMenuItem(
value: item.nmAgama.toString(),
child: Text(item.idAgama.toString()),
);
}).toList(),
onChanged: (newVal) {
setState(() {
dropdownAgama = newVal;
});
},
value: dropdownAgama,
),
],
);
} else {
return const Text('No Data');
}
}),
...
this is the model i am using which is converted from API
class Agama {
String? id;
String? idAgama;
String? nmAgama;
String? createdAt;
String? updatedAt;
dynamic createdBy;
dynamic updatedBy;
Agama(
{this.id,
this.idAgama,
this.nmAgama,
this.createdAt,
this.updatedAt,
this.createdBy,
this.updatedBy});
Agama.fromJson(Map<String, dynamic> json) {
id = json['id'];
idAgama = json['id_agama'];
nmAgama = json['nm_agama'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
createdBy = json['created_by'];
updatedBy = json['updated_by'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id'] = id;
data['id_agama'] = idAgama;
data['nm_agama'] = nmAgama;
data['created_at'] = createdAt;
data['updated_at'] = updatedAt;
data['created_by'] = createdBy;
data['updated_by'] = updatedBy;
return data;
}
}
it looks like you are not assigning your api data to the
List<Agama>? religion;
you can solve this by either mapping your snapshot data directly:
#override
void initState() {
super.initState();
BiodataProvider().getAgama();
}
var dropdownAgama;
...
FutureBuilder(
future: BiodataProvider().getBiodata(),
builder: (context, snapshot) {
if (snapshot.hasData) {
print(' ini Agama $religion');
return Column(
children: [
Text(
snapshot.data!.data!.name.toString(),
style: bold5,
),
DropdownButton(
hint: const Text('Religion'),
items: snapshot.data!.data!.map((item) {
return DropdownMenuItem(
value: item.nmAgama.toString(),
child: Text(item.idAgama.toString()),
);
}).toList(),
onChanged: (newVal) {
setState(() {
dropdownAgama = newVal;
});
},
value: dropdownAgama,
),
],
);
} else {
return const Text('No Data');
}
}),
or
by assigning the snapshot data to your list:
List<Agama>? religion = [];
#override
void initState() {
super.initState();
BiodataProvider().getAgama();
}
var dropdownAgama;
...
FutureBuilder(
future: BiodataProvider().getBiodata(),
builder: (context, snapshot) {
if (snapshot.hasData) {
WidgetsBinding.instance.addPostFrameCallback((_) {
setState((){
religion = snapshot.data!.data;
})
});
print(' ini Agama $religion');
return Column(
children: [
Text(
snapshot.data!.data!.name.toString(),
style: bold5,
),
DropdownButton(
hint: const Text('Religion'),
items: religion!.map((item) {
return DropdownMenuItem(
value: item.nmAgama.toString(),
child: Text(item.idAgama.toString()),
);
}).toList(),
onChanged: (newVal) {
setState(() {
dropdownAgama = newVal;
});
},
value: dropdownAgama,
),
],
);
} else {
return const Text('No Data');
}
}),
hope this helps!
Solution
In Controller Class,
Initialize your Future Method as your Model : Future<List<LeaveModel>> getLeaves(){}
create a List of Obj for Custom Class like this :
List<LeaveModel> leaveTypeObjList = [];
After fetching data from API add the datas in obj list via Object
type :LeaveModel leaveTypeObj = LeaveModel(leaveTypeResponseList[i]["LEAVE_TYPE_EN"]);
And in loop add it to your obj list: leaveTypeObjList.add(leaveTypeObj);
** In widget class at AsyncSnapshot use your List of Generics like this :
AsyncSnapshot<List<LeaveModel>>.
Demo Code
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main(List<String> args) {
runApp(MyHome());
}
class MyHome extends StatelessWidget {
const MyHome({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyApp(),
);
}
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<String> leaveTypeList = [];
int currentLeaveType = 0;
String? value;
String? selectedLeaveType;
late Future<List<LeaveModel>> futureLeaves;
#override
void initState() {
super.initState();
futureLeaves = FoodTypeController().getLeaves();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: double.infinity,
width: double.infinity,
child: Row(
children: [
Text(
"Leave Type = ",
style: TextStyle(fontSize: 24.0),
),
FutureBuilder(
future: futureLeaves,
builder: ((BuildContext context,
AsyncSnapshot<List<LeaveModel>> snapshot) {
if (snapshot.hasData) {
leaveTypeList = [];
List<LeaveModel>? LeaveTypes = snapshot.data;
for (int i = 0; i < LeaveTypes!.length; i++) {
leaveTypeList.add(LeaveTypes[i].leaveTypes!);
}
return SizedBox(
width: 200,
height: 50,
child: Container(
padding: EdgeInsets.only(left: 2.0, right: 4.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
border: Border.all(color: Colors.black, width: 1)),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
borderRadius: BorderRadius.circular(12),
value: currentLeaveType == null? null: leaveTypeList[currentLeaveType],
icon: Icon(Icons.arrow_drop_down_rounded),
items: leaveTypeList.map(buildMenuItem).toList(),
onChanged: (value) => setState(() {
currentLeaveType = leaveTypeList.indexOf(value.toString());
this.value = value;
selectedLeaveType = this.value;
}),
),
),
),
);
} else if (snapshot.hasError) {
return const Text("Error to load Snapshot");
} else {
return const CircularProgressIndicator();
}
})),
],
),
),
);
}
DropdownMenuItem<String> buildMenuItem(String item) => DropdownMenuItem(
value: item,
child: Text(
item.toString(),
style: TextStyle(fontWeight: FontWeight.w400, fontSize: 24.0),
),
);
}
class LeaveModel {
String? leaveTypes;
LeaveModel(this.leaveTypes);
}
class FoodTypeController {
Future<List<LeaveModel>> getLeaves() async {
List<LeaveModel> leaveTypeObjList = [];
String url = "";
http.Response response =
await http.post(Uri.parse(url), body: {"user": "", "pass": ""});
if (response.statusCode == 200) {
List leaveTypeResponseList = jsonDecode(response.body);
for (int i = 0; i < leaveTypeResponseList.length; i++) {
LeaveModel leaveTypeObj =
LeaveModel(leaveTypeResponseList[i]["LEAVE_TYPE"]);
leaveTypeObjList.add(leaveTypeObj);
}
return leaveTypeObjList;
} else {
throw Exception("Error to load data in Leave Controller");
}
}
}
Response
Visual

Although there is no error in the application that I want to show the weather from the internet, a white screen appears

launchUrl not working
import 'package:flutter/material.dart';
import 'package:haber_app/data/new_service.dart';
import 'package:haber_app/models/articles.dart';
import 'package:url_launcher/url_launcher.dart';
class Home extends StatefulWidget {
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<Articles> articles = [];
#override
void initState() {
NewsService.getNews().then((value) {
setState(() {
articles = value!;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Haberler'),
centerTitle: true,
),
body: Center(
child: ListView.builder(
itemCount: articles.length,
itemBuilder: (context, index) {
return Card(
child: Column(
children: [
Image.network(articles[index].urlToImage!),
ListTile(
leading: Icon(Icons.arrow_drop_down_circle),
title: Text(articles[index].title!),
subtitle: Text(articles[index].author!),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'açıklama açıklama açıklamaaçıklama açıklamaaçıklama'),
),
ButtonBar(
alignment: MainAxisAlignment.start,
children: [
ElevatedButton(
onPressed: () async {
await launchUrl(articles[index].url);
},
child: Text('Habere git'))
],
)
],
),
);
})),
);
}
}
Link of the code: https://github.com/ghedtoboss/haber_app
I am making a pull request, check the changes and merge. haber_app/pull/1
Changes are on
source.dart
class Source {
String? id;
String? name;
Source({this.id, this.name});
Source.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['name'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data['id'] = id;
data['name'] = name;
return data;
}
}
news.dart
import 'articles.dart';
class News {
String? status;
int? totalResults;
List<Articles>? articles;
News({this.status, this.totalResults, this.articles});
News.fromJson(Map<String, dynamic> json) {
status = json['status'];
totalResults = json['totalResults'];
if (json['articles'] != null) {
articles = <Articles>[];
json['articles'].forEach((v) {
print(v);
articles!.add(Articles.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = Map<String, dynamic>();
data['status'] = status;
data['totalResults'] = totalResults;
if (articles != null) {
data['articles'] = articles!.map((v) => v.toJson()).toList();
}
return data;
}
}
NewsService
import 'package:haber_app/models/articles.dart';
import 'package:haber_app/models/news.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class NewsService {
static NewsService _singleton = NewsService._internal();
NewsService._internal();
factory NewsService() {
return _singleton;
}
static Future<List<Articles>?> getNews() async {
String api =
'https://newsapi.org/v2/top-headlines?country=tr&category=business&apiKey=0002834b74c04acd987883986ea38f96';
final Uri url = Uri.parse(api);
final response = await http.post(url);
if (response.body.isNotEmpty) {
final responseJson = json.decode(response.body);
News news = News.fromJson(responseJson);
return news.articles;
}
return null;
}
}
On body
import 'package:flutter/material.dart';
import 'package:haber_app/data/new_service.dart';
import 'package:haber_app/models/articles.dart';
import 'package:url_launcher/url_launcher.dart';
class Home extends StatefulWidget {
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
List<Articles> articles = [];
#override
void initState() {
super.initState();
loadData();
}
loadData() async {
NewsService.getNews().then((value) {
print(value);
setState(() {
articles = value ?? [];
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Haberler'),
centerTitle: true,
),
body: Center(
child: articles.isEmpty
? Text("loading or something")
: ListView.builder(
itemCount: articles.length,
itemBuilder: (context, index) {
return Card(
child: Column(
children: [
if (articles[index].urlToImage != null)
Image.network(articles[index].urlToImage!),
ListTile(
leading: Icon(Icons.arrow_drop_down_circle),
title: Text(articles[index].title ?? ""),
subtitle: Text(articles[index].author ?? ""),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
'açıklama açıklama açıklamaaçıklama açıklamaaçıklama'),
),
ButtonBar(
alignment: MainAxisAlignment.start,
children: [
ElevatedButton(
onPressed: () async {
if (articles[index].url == null) {
return;
}
await launchUrl(
Uri.parse(articles[index].url!));
},
child: Text('Habere git'))
],
)
],
),
);
})),
);
}
}
You need to use Uri to launch
onPressed: () async {
if (articles[index].url == null) {
return;
}
await launchUrl(
Uri.parse(articles[index].url!));
},
Also make sure to set up the configurationsection
More about url_launcher

Flutter display server data / response from json

I have built a page which reads the json from recipeURL and I wish for it to display the product_name value in the json file. However for some reason my future fetchData () class isn't being read as none of the text in my if else statement is being displayed. Am I missing a simple oversight here?
EDIT: The main dart file is my main screen. This is where my navbar is created. Users are redirected to other pages when they click on the corresponding icon. Im having trouble passing BarcodePage(title:title); as parameters in my main file,26th line, can be found under Class MyAppState extends State<MyApp> {
My main dart file:
import 'package:flutter/material.dart';
import 'pages/BarcodePage.dart';
import 'pages/FoodPage.dart';
import 'pages/RecipePage.dart';
import 'pages/ShoppingPage.dart';
void main() {
runApp(MaterialApp(debugShowCheckedModeBanner: false, home: MyApp()),);
}
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState(){
return MyAppState();
}
}
class MyAppState extends State<MyApp> {
int _selectedPage =0;
final _pageOptions= [
FoodPage(),
RecipePage(),
BarcodePage(title: ,),
ShoppingPage(),
];
#override
Widget build(BuildContext context) {
return MaterialApp(
//title: 'Best B4',
theme: ThemeData(
primarySwatch: Colors.teal,),
debugShowCheckedModeBanner: false,
home: Scaffold (
appBar: AppBar(
title:Text(
'BestB4',
style: TextStyle(
fontFamily: 'PacificoRegular',
fontSize: 30,
),
),
backgroundColor: Colors.teal,
elevation: 20,
actions: [
IconButton(
icon: Icon(Icons.qr_code_2_rounded),
tooltip: 'Add item',
onPressed:(){
Navigator.push(
context,
MaterialPageRoute(builder: (context) => BarcodePage()));
},
)
],
//ONPRESSED MENU OPEN
),
body:_pageOptions[_selectedPage],
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
backgroundColor: Colors.teal,
selectedItemColor: Colors.white,
unselectedItemColor: Colors.white70,
iconSize: 40,
selectedFontSize: 15,
unselectedFontSize: 15,
currentIndex:_selectedPage,
onTap: (int index) {
setState(() {
_selectedPage = index;
});
},
items: [
BottomNavigationBarItem(
icon:Icon(Icons.restaurant_rounded),
label: 'Food',
), //, title:Text('Food')
BottomNavigationBarItem(
icon:Icon(Icons.menu_book_rounded),
label:'Recipes',
),//, title:Text('Recipes')
BottomNavigationBarItem(
icon:Icon(Icons.add_outlined),
label:'Add',
),//, title:Text('Add')
BottomNavigationBarItem(
icon:Icon(Icons.shopping_cart_rounded),
label:'Shopping',
),//,title:Text('Shopping')
],
),
),
);
}
}
My BarcodePage dart file:
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as p;
import 'package:flutter/services.dart';
import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:http/http.dart';
class BarcodePage extends StatefulWidget{
const BarcodePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_BarcodePageState createState() => _BarcodePageState();
}
var futuredata = {};
class _BarcodePageState extends State<BarcodePage> {
int counter=0;
String result= "";
Future _scanBarcode() async{
try{
ScanResult scanResult = await BarcodeScanner.scan();
String barcodeResult = scanResult.rawContent;
setState(() {
result = barcodeResult;
});
} on PlatformException catch (ex) {
if (ex.code == BarcodeScanner.cameraAccessDenied) {
setState((){
result = "CAMERA PERMISSION WAS DENIED. \n EDIT THIS IN YOUR SETTINGS";
});
}else {
setState(() {
result = "404 ERROR UNKNOWN $ex";
});
}
} on FormatException {
setState(() {
result = "SCAN AN ITEM";
});
} catch (ex){
setState(() {
result = "404 ERROR UNKNOWN $ex";
});
}
}
#override
void initState() {}
fetchmydata() async {
var request = p.Request(
'GET',
Uri.parse(
'https://world.openfoodfacts.org/api/v0/product/5060391623139.json'));
StreamedResponse response = await request.send();
if (response.statusCode == 200) {
// print(await response.stream.bytesToString());
var data = await response.stream.bytesToString();
futuredata = json.decode(data);
} else {
print(response.reasonPhrase);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.teal,
title:Text('Add an item',
style: TextStyle(
fontFamily: 'Fredoka',
fontSize: 25,
),
),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
FutureBuilder(
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting)
return Center(
child: Container(
child: CircularProgressIndicator(),
height: 50,
width: 50,
),
);
else if (snapshot.connectionState == ConnectionState.done)
return ListTile(
title: Text(futuredata["product"]["product_name"].toString()),
subtitle: Text("France:" +
futuredata["product"]["product_name_en"].toString()),
);
else {
return Container(
child: CircularProgressIndicator(),
height: 50,
width: 50,
);
}
},
future: fetchmydata(),
)
],
),
floatingActionButton: FloatingActionButton.extended(
backgroundColor: Color.fromRGBO(51, 171, 160, 100),
icon: Icon(Icons.camera_alt),
label: Text("Scan"),
onPressed: _scanBarcode,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
The Json file looks like this:
JSON LINK: https://world.openfoodfacts.org/api/v0/product/5060391623139.json
You can read your json like this
var futuredata = {};
var productname= futuredata["product"]["product_name"]
Your fetch method like this
fetchmydata() async {
var request = p.Request(
'GET',
Uri.parse(
'https://world.openfoodfacts.org/api/v0/product/5060391623139.json'));
StreamedResponse response = await request.send();
if (response.statusCode == 200) {
// print(await response.stream.bytesToString());
var data = await response.stream.bytesToString();
futuredata = json.decode(data);
} else {
print(response.reasonPhrase);
}
}
With model Class
SampleModel? Mymodel = null;
fetchmydata() async {
var request = p.Request(
'GET',
Uri.parse(
'https://world.openfoodfacts.org/api/v0/product/5060391623139.json'));
StreamedResponse response = await request.send();
if (response.statusCode == 200) {
// print(await response.stream.bytesToString());
var data = await response.stream.bytesToString();
futuredata = json.decode(data);
Mymodel = SampleModel.fromJson(futuredata);
} else {
print(response.reasonPhrase);
}
}
in the method we first read data from json as string or text
then we decode the string type or text from server to map type
SampleCode Dartpad live code check
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:http/http.dart' as p;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
var futuredata = {};
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
#override
void initState() {}
fetchmydata() async {
var request = p.Request(
'GET',
Uri.parse(
'https://world.openfoodfacts.org/api/v0/product/5060391623139.json'));
StreamedResponse response = await request.send();
if (response.statusCode == 200) {
// print(await response.stream.bytesToString());
var data = await response.stream.bytesToString();
futuredata = json.decode(data);
} else {
print(response.reasonPhrase);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
FutureBuilder(
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting)
return Center(
child: Container(
child: CircularProgressIndicator(),
height: 50,
width: 50,
),
);
else if (snapshot.connectionState == ConnectionState.done)
return ListTile(
title: Text(futuredata["product"]["product_name"].toString()),
subtitle: Text("France:" +
futuredata["product"]["product_name_en"].toString()),
);
else {
return Container(
child: CircularProgressIndicator(),
height: 50,
width: 50,
);
}
},
future: fetchmydata(),
)
],
),
);
}
}
Sample ModelClass
///
/// Code generated by jsonToDartModel https://ashamp.github.io/jsonToDartModel/
///
class SampleModelProduct {
/*
{
"_id": "5060391623139",
"_keywords": [
"peanut"
],
"product_name": "Peanut butter",
"product_name_en": "Peanut butter",
"product_name_fr": "Peanut butter"
}
*/
String? Id;
List<String?>? Keywords;
String? productName;
String? productNameEn;
String? productNameFr;
SampleModelProduct({
this.Id,
this.Keywords,
this.productName,
this.productNameEn,
this.productNameFr,
});
SampleModelProduct.fromJson(Map<String, dynamic> json) {
Id = json['_id']?.toString();
if (json['_keywords'] != null) {
final v = json['_keywords'];
final arr0 = <String>[];
v.forEach((v) {
arr0.add(v.toString());
});
Keywords = arr0;
}
productName = json['product_name']?.toString();
productNameEn = json['product_name_en']?.toString();
productNameFr = json['product_name_fr']?.toString();
}
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
data['_id'] = Id;
if (Keywords != null) {
final v = Keywords;
final arr0 = [];
v!.forEach((v) {
arr0.add(v);
});
data['_keywords'] = arr0;
}
data['product_name'] = productName;
data['product_name_en'] = productNameEn;
data['product_name_fr'] = productNameFr;
return data;
}
}
class SampleModel {
/*
{
"code": "5060391623139",
"product": {
"_id": "5060391623139",
"_keywords": [
"peanut"
],
"product_name": "Peanut butter",
"product_name_en": "Peanut butter",
"product_name_fr": "Peanut butter"
},
"status": 1,
"status_verbose": "product found"
}
*/
String? code;
SampleModelProduct? product;
int? status;
String? statusVerbose;
SampleModel({
this.code,
this.product,
this.status,
this.statusVerbose,
});
SampleModel.fromJson(Map<String, dynamic> json) {
code = json['code']?.toString();
product = (json['product'] != null)
? SampleModelProduct.fromJson(json['product'])
: null;
status = json['status']?.toInt();
statusVerbose = json['status_verbose']?.toString();
}
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
data['code'] = code;
if (product != null) {
data['product'] = product!.toJson();
}
data['status'] = status;
data['status_verbose'] = statusVerbose;
return data;
}
}
try creating a .g.dart file using flutter packages pub run build_runner build. flutter automatically will create your binding class factory. once you have the binding classes created flutter will automatically code your binding class, including nested classes. I personally think automation is the way to handle all interactions with json from the server. The reason you want to use the future .g.dart code generator is to reduce the possibility of error and incorrect type casting.
file.dart
factory ProductView.fromJson(Map<String, dynamic> json) =>
_$ProductFromJson(json);
Map<String, dynamic> toJson() => _$ProductViewToJson(this);
file.g.dart
ProductView _$ProductViewFromJson(Map<String, dynamic> json) {
return
ProductView(
json['field1'] as int,
json['field2'] as String,
json['field3'] == null
? null
: DateTime.parse(json['field3'] as String),
);
}
Map<String, dynamic> _$ProjectViewToJson(ProductView instance) =>
<String, dynamic>{
'field1': instance.field1,
'field2': instance.field2,
'field3': instance.field3?.toIso8601String(),
};
decoding the json
var client = http.Client();
Map<String, String> headers = new HashMap();
headers['Accept'] = 'application/json';
headers['Content-Type'] = 'application/json';
headers['Authorization'] = 'Bearer $token';
var response = await client.get(url, headers: headers).timeout(_TIMEOUT);
var parsed = json.decode(response.body);
var view = ProductView.fromJson(parsed);

How to display a list of map in firestore and shows them in flutter

I have the below model:
class UserInfoModel {
String? image;
String? name;
String? country;
String? city;
String? position;
List<UserSkills>? userSkills;
UserInfoModel(
{this.image, this.name, this.country, this.position, this.userSkills});
UserInfoModel.fromJson(dynamic json) {
image = json['user_image'];
name = json['name'];
country = json['country'];
city = json['city'];
position = json['position'];
userSkills = [
for (final skill in json['skills'] ?? []) UserSkills.fromJson(skill),
];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['user_image'] = this.image;
data['name'] = this.name;
data['country'] = this.country;
data['city'] = this.city;
data['position'] = this.position;
data['skills'] = [for (final skill in this.userSkills ?? []) skill.toJson()];
return data;
}
}
class UserSkills {
String? skillName;
String? skillPerc;
UserSkills({this.skillName, this.skillPerc});
UserSkills.fromJson(dynamic json) {
skillName = json['skill_name'];
skillPerc = json['skill_perc'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['skill_name'] = this.skillName;
data['skill_perc'] = this.skillPerc;
return data;
}
}
which is related to below image fire store:
I tried to create two methods one reads the user Info and the other method supposed to read the user skills, so here's the below code I have:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:haroonpf/enums/screen_state.dart';
import 'package:haroonpf/presentation/screens/home/models/user_info.dart';
import 'package:haroonpf/utils/constants.dart';
import '../../base_view_model.dart';
class HomeViewModel extends BaseViewModel {
UserInfoModel? userModel;
List<UserSkills> userSkills = [];
void getUserData() async {
await FirebaseFirestore.instance
.collection('users')
.doc(uId)
.get()
.then((value) {
// print("fbValues: " + value.data().toString());
userModel = UserInfoModel.fromJson(value.data());
}).catchError((error) {
print(error.toString());
});
setState(ViewState.Idle);
}
Future<List<UserSkills>> getUserSkills() async {
CollectionReference getSkills =
FirebaseFirestore.instance.collection('users');
await getSkills.get().then((snapshot) {
if (userSkills.isNotEmpty) userSkills.clear();
snapshot.docs.forEach((element) {
userSkills.add(UserSkills.fromJson(element.data()));
print("my skills:" + element.data().toString());
});
});
setState(ViewState.Idle);
return userSkills;
}
}
so in my Skills widget class I tried to retrieve data as the below code:
import 'package:flutter/material.dart';
import 'package:haroonpf/presentation/screens/home/viewmodel/home_view_model.dart';
import 'package:haroonpf/utils/animation/animated_progress_indicator.dart';
import 'package:haroonpf/utils/constants.dart';
import '../../../../../base_screen.dart';
class Skills extends StatelessWidget {
const Skills({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return BaseScreen<HomeViewModel>(onModelReady: (homeViewModel) {
homeViewModel.getUserSkills();
}, builder: (context, homeViewModel, _) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Divider(),
Padding(
padding: const EdgeInsets.symmetric(vertical: defaultPadding),
child: Text(
"Framework out skills",
style: Theme.of(context).textTheme.subtitle2,
),
),
SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Row(
children: [
...homeViewModel.userSkills.map(
(skills) => Expanded(
child: AnimatedCircularProgressIndicator(
percentage: double.parse(skills.skillPerc!),
label: skills.skillName.toString(),
),
),
),
],
),
),
],
);
});
}
}
but I found the below error:
Unexpected null value.
So it seems that because I didn't refers tot the doc id, as I tried to add the doc id it doesn't work...
So how can I retrieve the skills data to the AnimatedCircularProgressIndicator correctly?
Unexpected null value.
Do you know what line is causing this error?
I'm not sure I understand your approach to the HomeViewModel class. If you modify getUserData to return a Future<UserInfoModel> then you could just pass it to a FutureBuilder in your Skills widget:
class HomeViewModel extends BaseViewModel {
UserInfoModel? userModel;
Future<UserInfoModel> getUserData() async {
// not sure what setState does here but it was in the function to begin with
setState(ViewState.Idle);
// here I am returning a cached userModel.
// remove the following line of code if you don't actually want caching.
if (userModel != null) return userModel;
final value =
await FirebaseFirestore.instance.collection('users').doc(uId).get();
userModel = UserInfoModel.fromJson(value.data());
return userModel;
}
}
And then in your Skills widget, create the FutureBuilder, and then loop over the List<UserSkills> within your UserInfoModel.
class Skills extends StatelessWidget {
const Skills({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return BaseScreen<HomeViewModel>(onModelReady: (homeViewModel) {
// homeViewModel.getUserSkills();
}, builder: (context, homeViewModel, _) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Divider(),
Padding(
padding: const EdgeInsets.symmetric(vertical: defaultPadding),
child: Text(
"Framework out skills",
style: Theme.of(context).textTheme.subtitle2,
),
),
FutureBuilder<UserInfoModel>(
future: homeViewModel.getUserData(),
builder: (context, snapshot) => SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Row(
children: [
// loop over the skills to display each one
for (final skill in snapshot.data?.userSkills ?? [])
Expanded(
child: AnimatedCircularProgressIndicator(
percentage: double.parse(skill.skillPerc!),
label: skill.skillName.toString(),
),
),
],
),
),
),
],
);
});
}
}

In Flutter how to create auto infinite scroll pagination by page id?

I am trying to create pagination with auto-scroll but with this model (in the bottom), I am unable to do? I am a beginner here in the flutter I tried hard from my end but unfortunately was unable to find out. So can someone plz help me to create infinite auto-scroll pagination in this flutter screen?
Here are my test screen codes:
class Test extends StatefulWidget {
Test({Key key}) : super(key: key);
#override
createState() => _Test();
}
class _Test extends State<Test3> {
Future<getTotalLeadsListss> getLeads;
String _value='total';
#override
void initState() {
super.initState();
loading=false;
getLeads=_getDatacall();
}
int page =1;
ScrollController _scrollController = new ScrollController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FutureBuilder<getTotalLeadsListss>(
future: _getDatacall(),
builder: (context, snapshot) {
if (snapshot.hasData) {
var dataB =snapshot.data;
return dataB.leadFollowupss.length<=0?
Center(child: Column(
children: [
Image(image:AssetImage(Assets.noDataImg),)
],
)):
ListView.builder(
controller: _scrollController,
itemCount:dataB.leadFollowupss.length,
itemBuilder: (BuildContext context, int index){
return Container(
margin: EdgeInsets.only(left: 8.0,right: 8.0,top: 3.0,bottom: 3.0),
child: GestureDetector(
onTap:(){},
child: Card(
color: Colors.grey,
elevation: 2.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
child: ListTile(
contentPadding: EdgeInsets.only(left:8.0,right:8.0),
title: new Text(dataB.leadFollowupss[index].name,maxLines: 1,
overflow: TextOverflow.ellipsis,
softWrap: false,
style: TextStyle(
fontSize: 18.0,fontWeight: FontWeight.w600),
),
subtitle: Text(
dataB.leadFollowupss[index].nextMeeting.toString(),
style: TextStyle(),
),
)
)
)
);
}
);
}
else if (snapshot.hasError) {
return Text("${snapshot.error}");
} else if (snapshot.connectionState==ConnectionState.waiting){
return Container(child: Center(child: Image(image:AssetImage(Assets.loaderImg),)));
}
return Container(child: Center(child: Image(image:AssetImage(Assets.loaderImg),)));
},
)
),
);
}
Future<getTotalLeadsListss> _getDatacall()async{
TotalLeadsListss wrapper = new TotalLeadsListss();
return wrapper.getAllLeadsListss(_value,page);
}
}
/// get all leads list
class TotalLeadsListss {
String _value;
Future<getTotalLeadsListss> getAllLeadsListss(_value,page) async {
final response = await http.post(Uri.parse('${mainUrl}lead-list'),
headers:{
'Accept': 'application/json',
HttpHeaders.authorizationHeader: 'Bearer $accessToken',
},
body: {
'type':'$_value',
'page':'$page',
}
);
if (response.statusCode == 200) {
String data = response.body;
return getTotalLeadsListss.fromJson( json.decode(response.body) );
} else {
print('failed to get data');
throw Exception('No records found');
}
}
}
class getTotalLeadsListss {
bool status;
String msg;
List<LeadFollowupss> leadFollowupss;
getTotalLeadsListss({this.status, this.msg, this.leadFollowupss});
getTotalLeadsListss.fromJson(Map<String, dynamic> json) {
status = json['status'];
msg = json['message'];
if (json['data'] != null) {
leadFollowupss = new List<LeadFollowupss>();
json['data'].forEach((v) {
leadFollowupss.add(new LeadFollowupss.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['message'] = this.msg;
if (this.leadFollowupss != null) {
data['data'] = this.leadFollowupss.map((v) => v.toJson()).toList();
}
return data;
}
}
class LeadFollowupss {
String id,name,nextMeeting;
LeadFollowupss(
{this.id,this.name,this.nextMeeting});
LeadFollowupss.fromJson(Map<String, dynamic> json) {
id = json['id'];
name = json['business_name'];
nextMeeting=json['next_meeting'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['business_name'] = this.name;
data['next_meeting'] = this.nextMeeting;
return data;
}
}
You need to listen ScrollController
class MyHome extends StatefulWidget {
#override
_MyHomeState createState() => _MyHomeState();
}
class _MyHomeState extends State<MyHome> {
late ScrollController controller;
List<String> items = List.generate(20, (index) => 'item $index');
#override
void initState() {
super.initState();
controller = ScrollController()..addListener(_scrollListener);
}
#override
void dispose() {
controller.removeListener(_scrollListener);
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
child: ListView.builder(
controller: controller,
itemBuilder: (context, index) {
return Text(items[index]);
},
itemCount: items.length,
),
);
}
void _scrollListener() {
print(controller.position.extentAfter);
if (controller.position.extentAfter < 500) {
setState(() {
items.addAll(List.generate(20, (index) => 'item $index'));
});
}
}
}
if you got data from server request data in setState with range you need each when user scrolled down