hey guys I'm new to Flutter, and I'm turning to build a very simple chat app for learning purposes, I'm using StreamBulider for that, it shows me no errors, but it's not working
I tread to add Text Widget on its own without the streambuilder so I can make sure that the problem with the streambulder function not anything else and it's works fine
can anyone help find what went wrong?
here is my code
import 'package:flutter/material.dart';
import 'package:flash_chat/constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class ChatScreen extends StatefulWidget {
static String id = 'chat_screen';
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final _fireStore = FirebaseFirestore.instance;
final _auth = FirebaseAuth.instance;
late String messegeText;
late User loogedInUser;
#override
void initState() {
super.initState();
getCurrentUser();
}
//------------------------------------------------------------------------------
// GetCurrentUser Method...
void getCurrentUser() async {
try {
// ignore: await_only_futures
final user = await _auth.currentUser;
if (user != null) {
loogedInUser = user;
}
} catch (e) {
print(e);
}
}
//------------------------------------------------------------------------------
// Get Masseges Method...
void messegesStream() async {
await for (var snapshot in _fireStore.collection('messeges').snapshots()) {
for (var message in snapshot.docs) {
print(message.data());
}
}
}
//------------------------------------------------------------------------------
// Code Start...
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurpleAccent,
leading: null,
actions: <Widget>[
IconButton(
icon: const Icon(Icons.download),
onPressed: () {
messegesStream();
// _auth.signOut();
// Navigator.pop(context);
}),
],
title: const Text('⚡️Chat'),
),
body: Container(
constraints: const BoxConstraints.expand(),
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("images/background.jpg"), fit: BoxFit.cover),
),
child: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
//------------------------------------------------------------
// StreamBuilder method...
StreamBuilder<QuerySnapshot>(
stream: _fireStore.collection('messages').snapshots(),
builder: (context, snapshot) {
List<Text> messageWidgets = [];
if (snapshot.hasData) {
final messages = snapshot.data!.docs;
for (var message in messages) {
final messageText = message.get('text');
final messageSender = message.get('sender');
final messageWidget =
Text('$messageSender said $messageText');
messageWidgets.add(messageWidget);
}
}
return Column(
children: messageWidgets,
);
},
),
//------------------------------------------------------------
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
onChanged: (value) {
messegeText = value;
},
decoration: kMessageTextFieldDecoration,
),
),
MaterialButton(
onPressed: () {
_fireStore.collection('messeges').add(
{
'text': messegeText,
'sender': loogedInUser.email,
},
);
},
child: const Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
),
);
}
}
my android emulator screen,
Try this code:
StreamBuilder<QuerySnapshot>(
stream: _fireStore.collection('messages').snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> chatSnapshot) {
if (chatSnapshot.connectionState == ConnectionState.waiting) {
return Center(
child: Container(),
);
}
return ListView(
reverse: true,
controller: _controller,
physics: const BouncingScrollPhysics(),
children:
chatSnapshot.data!.docs.map((DocumentSnapshot document) {
Map<String, dynamic> data =
document.data()! as Map<String, dynamic>;
return Text(data["text"]);
}).toList(),
);
},
),
Related
am trying to call the user from data (am using firebase as database)
the profile page not working for more understanding check the other issue i posted last day :
FirebaseException ([cloud_firestore/unavailable] The service is currently unavailable , and how to solve it
import 'package:cached_network_image/cached_network_image.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:yumor/models/progress.dart';
import 'package:yumor/models/user_model.dart';
class profile extends StatefulWidget {
const profile({Key? key,required this.userProfile}) : super(key: key);
final String? userProfile;
#override
State<profile> createState() => _profileState();
}
class _profileState extends State<profile> {
final userRef = FirebaseFirestore.instance.collection('users');
buildprofileheader() async{
final doc=await userRef.doc(widget.userProfile).get();
if(doc.exists){
var data=doc.data();
}
return FutureBuilder(future:FirebaseFirestore.instance.collection('users').doc(userRef.id).get(),
builder: ((context, snapshot) {
if(!snapshot.hasData){
return CircularProgress();
}
UserModel user=UserModel.fromMap(Map);
return Padding(padding:EdgeInsets.all(16.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.account_circle, size: 90,)
],
),
Container(
alignment: Alignment.center,
padding: EdgeInsets.all(12.0),
child: Text(
user.Username as String,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize:16.0,
),
),
),
],
),
);
}),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(
"Profile",
),
),
body: ListView(children: <Widget>[
buildprofileheader(), // the error shows in this line <=======
]));
}
}
Your buildprofileheader return type is Future<Widget> but it should be Widget in order to use in ListView, so you need to use an other FutureBuilder to get userRef. So just wrap your current FutureBuilder with an other one.
As for the logic part, you can simplify the logic for future method something like
Future<UserModel?> getData() async {
try{
final userRef = FirebaseFirestore.instance.collection('users');
final doc = await userRef.doc(widget.userProfile).get();
if (doc.exists) {
var data = doc.data(); // not sure about this use case
} else {
return null;
}
final data = await FirebaseFirestore.instance
.collection('users')
.doc(userRef.id)
.get();
if (data.exists) {
UserModel user = UserModel.fromMap(data);
return user;
}
} catch(e){ }
}
Create a state variable for future method , and use like
late final future = getData();
Widget buildprofileheader() {
return FutureBuilder<UserModel?>(
future: future,
builder: ((context, snapshot) {
if (!snapshot.hasData) {
return CircularProgress();
}
return Padding(....
class _profileState extends State<profile> {
Future<UserModel?> getData() async {
final userRef = FirebaseFirestore.instance.collection('users');
final doc = await userRef.doc(widget.userProfile).get();
if (doc.exists) {
var data = doc.data(); // not sure about this use case
} else {
return null;
}
final data = await FirebaseFirestore.instance
.collection('users')
.doc(userRef.id)
.get();
if (data.exists) {
UserModel user = UserModel.fromMap(data);
return user;
}
}
late final future = getData();
Widget buildprofileheader() {
return FutureBuilder<UserModel?>(
future: future,
builder: ((context, snapshot) {
if (!snapshot.hasData) {
return CircularProgressIndicator();
}
return Padding(
padding: EdgeInsets.all(16.0),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.account_circle,
size: 90,
)
],
),
Container(
alignment: Alignment.center,
padding: EdgeInsets.all(12.0),
child: Text(
user.Username as String,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16.0,
),
),
),
],
),
);
}),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(
"Profile",
),
),
body: ListView(children: <Widget>[
buildprofileheader(),
]));
}
}
I was trying to get the data from firebase to my chat screen using snapshot data but I am unable to get that as the message.data['text'] and sender gives me error. I want to display the name and the message all on the screen for now so please suggest the fix for this code or a alternative way for that
message code
import 'package:flutter/material.dart';
import 'package:flash_chat/constants.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class ChatScreen extends StatefulWidget {
static String id = 'chat_screen';
#override
_ChatScreenState createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final _firestore = FirebaseFirestore.instance;
final _auth = FirebaseAuth.instance;
User loggedInUser;
String message;
#override
void initState() {
// TODO: implement initState
getCurrentUser();
super.initState();
}
void getCurrentUser() {
try {
final user = _auth.currentUser;
if (user != null) {
loggedInUser = user;
// print(loggedInUser.email);
}
} catch (e) {
print(e);
}
}
void messageStream() async {
await for (var snapshot in _firestore.collection('messages').snapshots()) {
for (var message in snapshot.docs) {
print(message.data());
}
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: null,
actions: <Widget>[
IconButton(
icon: Icon(Icons.close),
onPressed: () {
messageStream();
//Implement logout functionality
}),
],
title: Text('⚡️Chat'),
backgroundColor: Colors.lightBlueAccent,
),
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
StreamBuilder<QuerySnapshot>(
stream: _firestore.collection('messages').snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
backgroundColor: Colors.lightBlueAccent,
),
);
}
final messages = snapshot.data.docs;
List<Text> messagesWidgets = [];
for (var message in messages) {
final messageText = message.data['text']; //error
final messageSender = message.data['sender']; //error
final messageWidget = Text('$messageText from
$messageSender');
messageWidgets.add(messageWidget)
}
return Column(
children: messagesWidgets,
);
},
),
Container(
decoration: kMessageContainerDecoration,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
onChanged: (value) {
message = value;
//Do something with the user input.
},
decoration: kMessageTextFieldDecoration,
),
),
FlatButton(
onPressed: () {
//message + loggedInuser.email
//Implement send functionality
_firestore.collection('messages').add({
'text': message,
'sender': loggedInUser.email,
});
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
),
],
),
),
);
}
}
I want to create load more scrollview in listview. My app flow is storing youtube link in csv file and fetch this link from my app and display in my listview. But the problem is I don't want to wait too much load time when app is open.If I have a lot of youtube link in my csv.I will take a lot of time.So,for example I want to display only 5 video in initial state and when load more, display more 5 video in my list view.How can I do that.My code is below.
import 'package:flutter/material.dart';
import 'package:youtube_player_flutter/youtube_player_flutter.dart';
import 'videolist.dart';
import './models/models.dart';
import 'package:csv/csv.dart' as csv;
import 'package:http/http.dart' as http;
class DisplayVideo extends StatefulWidget {
String id;
#override
DisplayVideo(this.id);
_DisplayVideoState createState() => _DisplayVideoState();
}
class _DisplayVideoState extends State<DisplayVideo> {
late YoutubePlayerController _controller ;
Future<List<YoutubeDetail>> _loadCSV() async {
Map<String, String> allData = {
'login': '',
'password': '',
};
final Uri url = Uri.parse(
'https://raw.githubusercontent.com/JornaldRem/bedtime_story/main/videoId.csv');
final response = await http.get(url);
csv.CsvToListConverter converter =
new csv.CsvToListConverter(eol: '\r\n', fieldDelimiter: ',');
List<List> listCreated = converter.convert(response.body);
// the csv file is converted to a 2-Dimensional list
List<YoutubeDetail> youtubeDetailList = [];
for (int i = 0; i < listCreated.length; i++) {
YoutubeDetail temp = YoutubeDetail(
listCreated[i][0],
listCreated[i][1],
);
youtubeDetailList.add(temp);
}
return youtubeDetailList;
}
#override
void initState() {
// TODO: implement initState
super.initState();
_controller = YoutubePlayerController(
initialVideoId: widget.id,
flags: YoutubePlayerFlags(
autoPlay: true,
mute: false,
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
title: Text('Title'),
toolbarHeight: 60,
backgroundColor: const Color(0xFF006666),
),
body: Column(
children: [
Container(
child: YoutubePlayer(
controller: _controller,
liveUIColor: Colors.amber,
),
),
Expanded(
child: Container(
child: FutureBuilder(
future: _loadCSV(),
builder: (BuildContext context,
AsyncSnapshot<List<YoutubeDetail>> snapshot) {
if (snapshot.hasData) {
List<YoutubeDetail> videoDetail = snapshot.data!;
return ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.vertical,
itemCount: videoDetail.length,
itemBuilder: (_, int index) {
if (index > 0) {
return GestureDetector(
child: Container(
height: 80,
child: DisplayVideoView(
videoDetail[index].url,
videoDetail[index].title),
),
onTap: (){
String url = videoDetail[index].url;
String id = url.substring(url.length - 11);
print("HEllo");
_controller.load(id);
// DisplayVideo(id);
}
);
} else {
return Container();
}
});
} else {
return Container();
}
}),
),
),
],
));
}
}
class DisplayVideoView extends StatelessWidget {
String videopath;
String title;
DisplayVideoView(this.videopath, this.title);
#override
Widget build(BuildContext context) {
String url = videopath;
String id = url.substring(url.length - 11);
// TODO: implement build
return Card(
clipBehavior: Clip.antiAlias,
child: Container(
height: 150,
padding: const EdgeInsets.all(0),
child: Row(children: [
Expanded(
flex: 6,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
'https://img.youtube.com/vi/$id/mqdefault.jpg'),
fit: BoxFit.fill)),
),
),
Spacer(
flex: 1,
),
Expanded(
flex: 14,
child: Container(
padding: const EdgeInsets.only(top: 2),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(title,
style: TextStyle(
fontSize: 16.0, fontWeight: FontWeight.bold)),
],
),
),
),
]),
),
);
}
}
What do you think about this approach:
import 'package:flutter/material.dart';
class ExampleWidget extends StatefulWidget {
const ExampleWidget({Key? key}) : super(key: key);
#override
_ExampleWidgetState createState() => _ExampleWidgetState();
}
class _ExampleWidgetState extends State<ExampleWidget> {
List<Widget> _myList = [];
void _loadFiveMore() {
_myList = <Widget>[
..._myList,
for (int i = _myList.length; i < _myList.length + 5; i++)
ListTile(title: Text('item $i')),
];
}
#override
void initState() {
_loadFiveMore();
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: ListView(children: [
..._myList,
OutlinedButton(
onPressed: () {
setState(() => _loadFiveMore());
},
child: const Text('get 5 more'))
]),
),
);
}
}
void main() {
runApp(const ExampleWidget());
}
You can use this package.
have loadmore callback, refresh call back
https://pub.dev/packages/loadmore_listview
I am trying to implement pagination in my app when a user searches for something.
I have been able to fetch and display my data(limited to like 12 results) but I have been unable to get more results due to Search Delegate not being a stateful class.
Is there a way I can use setState effectively to load more data by adding to my already fetched listView?
Code
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:official_coolkicks/models/shoe.dart';
import 'package:official_coolkicks/providers/search-provider.dart';
import 'package:official_coolkicks/providers/shoe-provider.dart';
import 'package:official_coolkicks/themes/adjust_settings_icons.dart';
import 'package:official_coolkicks/views/widgets/category/shoeCard.dart';
import 'package:official_coolkicks/views/widgets/filtering/filter_chip.dart';
import 'package:provider/provider.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
class CategorySearch extends SearchDelegate<Shoe> {
#override
ThemeData appBarTheme(BuildContext context) {
assert(context != null);
final ThemeData theme = Theme.of(context);
assert(theme != null);
return theme;
}
ScrollController _sc = new ScrollController();
List<Shoe> shoes;
int page = 1;
bool isLoading = false;
#override
String get searchFieldLabel => 'Search in Men\'s Shoes';
var random = new Random();
Future _saveList() async {
SharedPreferences.getInstance().then((prefs) {
prefs.setStringList("searchHistory", searchHistory);
});
}
Widget content;
#override
List<Widget> buildActions(BuildContext context) {
return [
IconButton(
icon: Icon(Icons.clear),
onPressed: () {
query = "";
},
)
];
}
#override
Widget buildLeading(BuildContext context) {
return IconButton(
icon: AnimatedIcon(
icon: AnimatedIcons.menu_arrow,
progress: transitionAnimation,
),
onPressed: () {
close(context, null);
});
}
#override
Widget buildResults(BuildContext context) {
final double height = MediaQuery.of(context).size.height;
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
void loadMore() {
setState(() {
page++;
isLoading = true;
print('ISLOADING IS EQUALS TO $isLoading');
});
}
setState(() {
if (page > 1) {
page++;
print('PAGE IS NOW $page');
}
});
return FutureBuilder(
future: _search(page),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
print(snapshot.error);
return Center(
child: Text('Check your Internet connection and try again'),
);
} else if (snapshot.data.length == 0) {
return Center(
child: Text('No search results found'),
);
}
return Container(
height: height,
child: Stack(
children: [
Column(
children: <Widget>[
Expanded(
child: NotificationListener<ScrollNotification>(
child: GridView.count(
padding: EdgeInsets.all(15),
controller:
new ScrollController(keepScrollOffset: false),
shrinkWrap: true,
childAspectRatio:
MediaQuery.of(context).size.width /
(MediaQuery.of(context).size.height / 1.3),
scrollDirection: Axis.vertical,
crossAxisCount: 2,
crossAxisSpacing: 15,
mainAxisSpacing: 15,
children: List.generate(
snapshot.data.length,
(index) {
return ShoeCard(
index: random.nextInt(1000000),
shoe: snapshot.data[index]);
},
),
),
onNotification: (ScrollNotification scrollInfo) {
if (scrollInfo.metrics.pixels ==
scrollInfo.metrics.maxScrollExtent) {
// loadMore();
}
return false;
},
)),
],
),
Align(
alignment: FractionalOffset.bottomCenter,
child: Container(
height: isLoading ? 50 : 0,
child: Center(
child: CircularProgressIndicator(),
))),
Align(
alignment: FractionalOffset.bottomRight,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FloatingActionButton(
child: Icon(AdjustSettings.adjust),
backgroundColor: Colors.deepPurple,
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => FilterChipDisplay()));
},
),
),
),
],
));
} else {
return Center(
child: CircularProgressIndicator(),
);
}
},
);
});
}
#override
Widget buildSuggestions(BuildContext context) {
// List<Product> shoeList = products;
return Container();
}
Future<List<Shoe>> _search(int page) async {
String baseurl = "https://coolke.herokuapp.com";
String formatter(String url) {
return baseurl + url;
}
String url = formatter('/coolke/getCategorySearch/Men/$query?$page');
final result = await http.get(url);
final nlist = json.decode(result.body);
final list = nlist['shoes'] as List;
return list.map((e) => Shoe.fromJson(e)).toList();
}
}
I am building a project about coronavirus tracker for my class. Everytime I tried to call the api and hit the serach icon it throw an error in the console. I have tried many things but it throw the same error. can anyone help figure out what is wrong with code?
class _HomePageState extends State<HomePage> {
List <Data> data = [];
var countryController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Center(child: Text('CoronaVirus Tracker')),
),
body: Column(
children: <Widget>[
Row(
children: <Widget>[
Expanded(
child: TextField(
decoration: InputDecoration(
border: InputBorder.none, hintText: 'Enter a Country'),
controller: countryController,
),
),
IconButton(
icon: Icon(Icons.search),
color: Colors.blue,
onPressed: () {
fetchData().then((newData) {
setState(() {
data = newData as List<Data>;
});
});
}),
],
),
//The search item appear here
Expanded(
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Card(
child: ListTile(
title: Text(data[index].country),
subtitle: Text(data[index].cases),
onTap: () => {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
Text('This is a new page!!')))
},
),
);
},
itemCount: data.length,
),
),
],
));
}
Here is the Api code
Future <Data> fetchData() async {
final response = await http.get('https://api.covid19api.com/live/country/malaysia/status/confirmed');
if (response.statusCode == 200) {
print(response.body);
// Transform json into object
return Data.fromJson(json.decode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load data');
}
}
}
Here is the constructor
class Data {
final String date;
final String country;
final String cases;
Data({this.date, this.country, this.cases});
factory Data.fromJson(Map<String, dynamic> json) {
return Data(
country: json['Country'],
date: json['Date'],
cases: json['Cases']);
}
}
From the above mentioned code I have created the a sample for you.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool _isLoading = false;
List<Data> data = List();
TextEditingController countryController = TextEditingController();
Future<List<Data>> fetchData(String countryName) async {
setState(() {
_isLoading = true;
});
//https://api.covid19api.com/live/country/india/status/confirmed
final response = await http.get(
'https://api.covid19api.com/live/country/$countryName/status/confirmed');
print(response.statusCode);
if (response.statusCode == 200) {
print(response.body);
// Transform json into object
var items = json.decode(response.body);
items.forEach((item) {
data.add(Data.fromJson(item));
});
return data;
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load data');
}
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Center(child: Text('CoronaVirus Tracker')),
),
body: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Expanded(
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'Enter a Country'),
controller: countryController,
),
),
IconButton(
icon: Icon(Icons.search),
color: Colors.blue,
onPressed: () {
fetchData(countryController.text).then((newData) {
setState(() {
data = newData;
_isLoading = false;
});
});
}),
],
),
),
_isLoading
? CircularProgressIndicator()
:
//The search item appear here
Expanded(
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Card(
child: ListTile(
title: Text(data[index].date.toString()),
subtitle: Text(data[index].cases.toString()),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
Text('This is a new page!!')));
},
),
);
},
itemCount: data.length,
),
),
],
)),
);
}
}
class Data {
final String date;
final String country;
final int cases;
Data({this.date, this.country, this.cases});
factory Data.fromJson(Map<String, dynamic> json) {
return Data(
country: json['Country'], date: json['Date'], cases: json['Active']);
}
}
Change the model class parameters as you like.
Just check out and let me know if it works.