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
Related
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
I am facing a couple of issues, I'm trying to integrate my Google Calendar inside my app, but I get some issues "CalendarScope isn't defined for the type 'CalendarApi'.
As you can see in the screenshot below, there are some issues, but I don't know how fix them.
I am taking it from this code
https://www.syncfusion.com/kb/12647/how-to-load-the-google-calendar-events-to-the-flutter-calendar-sfcalendar-in-ios
I leave you here my code, could you please help me to figure out how to fix this?
class CalendarPage extends StatefulWidget {
#override
_CalendarPage createState() => _CalendarPage();
}
class _CalendarPage extends State<CalendarPage> {
final GoogleSignIn _googleSignIn = GoogleSignIn(
clientId:
'OAuth Client ID',
scopes: <String>[
googleAPI.CalendarApi.CalendarScope,
],
);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue[900],
centerTitle: true,
elevation: 0,
title: const Text("Calendario Scadenze",
style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.w600, fontFamily: "Raleway"),
),
leading: Builder(
builder: (BuildContext context) {
return IconButton(
icon: const Icon(
Icons.arrow_back_ios,
color: Colors.white,
),
onPressed: () {
Navigator.of(context).pop();
},
);
},
),
),
backgroundColor: Colors.white,
body: FutureBuilder(
future: getGoogleEventsData(),
builder: (BuildContext context, AsyncSnapshot snapshot) {
return Stack(
children: [
SfCalendar(
view: CalendarView.month,
initialDisplayDate: DateTime(2020,7,15,9,0,0),
dataSource: GoogleDataSource(events: snapshot.data),
monthViewSettings: const MonthViewSettings(
appointmentDisplayMode:
MonthAppointmentDisplayMode.appointment),
),
snapshot.data != null
? Container()
: const Center(
child: CircularProgressIndicator(),
)
],
);
},
),
);
}
#override
void dispose(){
if(_googleSignIn.currentUser != null) {
_googleSignIn.disconnect();
_googleSignIn.signOut();
}
super.dispose();
}
Future<List<googleAPI.Event>> getGoogleEventsData() async {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn();
final GoogleAPIClient httpClient =
GoogleAPIClient(await googleUser!.authHeaders);
final googleAPI.CalendarApi calendarAPI = googleAPI.CalendarApi(httpClient);
final googleAPI.Events calEvents = await calendarAPI.events.list(
"primary",
);
final List<googleAPI.Event> appointments = <googleAPI.Event>[];
if (calEvents.items != null) {
for (int i = 0; i < calEvents.items!.length; i++) {
final googleAPI.Event event = calEvents.items![i];
if (event.start == null) {
continue;
}
appointments.add(event);
}
}
return appointments;
}
}
class GoogleDataSource extends CalendarDataSource {
GoogleDataSource({required List<googleAPI.Event> events}) {
appointments = events;
}
#override
DateTime getStartTime(int index) {
final googleAPI.Event event = appointments![index];
return event.start!.date ?? event.start!.dateTime!.toLocal();
}
#override
bool isAllDay(int index) {
return appointments![index].start.date != null;
}
#override
DateTime getEndTime(int index) {
final googleAPI.Event event = appointments![index];
return event.endTimeUnspecified != null
//&& event.endTimeUnspecified
? (event.start!.date ?? event.start!.dateTime!.toLocal())
: (event.end!.date != null
? event.end!.date!.add(const Duration(days: -1))
: event.end!.dateTime!.toLocal());
}
#override
String getLocation(int index) {
return appointments![index].location;
}
#override
String getNotes(int index) {
return appointments![index].description;
}
#override
String? getSubject(int index) {
final googleAPI.Event event = appointments![index];
return event.summary == null || event.summary!.isEmpty
? 'No Title'
: event.summary;
}
}
class GoogleAPIClient extends IOClient {
final Map<String, String> _headers;
GoogleAPIClient(this._headers) : super();
#override
Future<IOStreamedResponse> send(BaseRequest request) =>
super.send(request..headers.addAll(_headers));
#override
Future<Response> head(Object url, {required Map<String, String> headers}) =>
super.head(url, headers: headers..addAll(_headers));
}
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
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 ?? ''),
],
),
],
),
);
},
),
);
}
}
class Organization_Api{
static Future<List<dynamic>> getData(
{required String target, String? limit}) async {
try {
var uri = Uri.https(
BASE_URL,
"api/$target",
target == "organizations"
? {
"offset": "0",
"limit": limit,
}
: {});
var response = await http.get(uri);
var data = jsonDecode(response.body);
List tempList = [];
if (response.statusCode != 200) {
throw data["message"];
}
for (var v in data) {
tempList.add(v);
}
return tempList;
} catch (error) {
log("An error occured $error");
throw error.toString();
}
}
static Future<List<Organization>> getAllOrganizations(
{required String limit}) async {
List temp = await getData(
target: "organizations",
limit: limit,
);
return Organization.organizationsToList(temp);
}
static Future<Organization> getOrganizationById({required String id}) async {
try {
var uri = Uri.https(
BASE_URL,
"api/organizations/$id",
);
var response = await http.get(uri);
var data = jsonDecode(response.body);
if (response.statusCode != 200) {
throw data["message"];
}
return Organization.fromJson(data);
} catch (error) {
log("an error occured while getting organization info $error");
throw error.toString();
}
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
static String routeName = "/home";
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
Future<List<Organization>>? result ;
void initState(){
result = Organization_Api.getAllOrganizations(limit: '4');
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Organizations", style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.white,
centerTitle: true,
),
body: Padding(
padding: EdgeInsets.all(10.0),
child: Column(
children:
<Widget>[
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children:<Widget>[
ListView(
shrinkWrap: true,
children:<Widget> [result],
)
],
),
)
],
),
),
);
}
}
class Organization{
final int OrganizationId;
final String OrganizationName;
Organization({required this.OrganizationId,required this.OrganizationName});
factory Organization.fromJson(Map<String,dynamic> json){
return Organization(OrganizationId: json['OrganizationId'], OrganizationName: json['OrganizationName']);
}
Map toJson(){
return{
"OrganizationId": this.OrganizationId,
"OrganizationName": this.OrganizationName,
};
}
static List<Organization> organizationsToList(List organizationToList) {
return organizationToList.map((data) {
return Organization.fromJson(data);
}).toList();
}
}
Error = The element type >'Future<List>?' can't be assigned to the list type 'Widget'.
I just want to check the data coming from the service, but I couldn't find how to do it.
What did I do wrong or what did I miss to list the incoming data?
I shared the screen page and the codes on how I got the information from the service.
Your Organization_Api.getAllOrganizations provide a future. You can use FutureBuilder.
class _HomeScreenState extends State<HomeScreen> {
Future<List<Organization>>? myFuture;
#override
void initState() {
myFuture = Organization_Api.getAllOrganizations(limit: '4');
super.initState();
}
And on future builder
FutureBuilder<List<Organization>?>(
future: myFuture,
builder: (context, snapshot) {
if (snapshot.hasData && snapshot.data!.isNotEmpty) {
return ListView(
shrinkWrap: true,
//children: snapshot.data!, // when `Organization` is a widget
children:// when `Organization` is a data model class
snapshot.data!.map((e) => Text(e.toString())).toList(),
);
}
return CircularProgressIndicator();
},
)
Also check Randal L. Schwartz video on using Future