I have 3 int variable that I want to update via a void function during an initstate. I tried printing them out and the value is correct but when I try to display them in my container, it still shows 0.
int equipmentCount1 = 0;
int equipmentCount2 = 0;
int equipmentCount3 = 0;
#override
void initState() {
getEquipmentCount('Hammer', equipmentCount1);
getEquipmentCount('Spanner', equipmentCount2);
getEquipmentCount('Screwdriver', equipmentCount3);
super.initState();
}
void getEquipmentCount(String type, int counter) async {
await Firestore.instance
.collection('Notes')
.document('CarNotes')
.collection('PM Overview')
.document(type)
.collection(type)
.getDocuments()
.then((QuerySnapshot snapshot) {
setState(() {
return counter = snapshot.documents.length;
});
});
print(counter);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(equipmentCount1),
Text(equipmentCount2),
Text(equipmentCount3),
You should pass in a callback function so the state can be updated.
Here's an example:
#override
void initState() {
getEquipmentCount('Hammer', (int count) => setState(() {
equipmentCount1 = count;
}));
// same for the others
super.initState();
}
void getEquipmentCount(String type, ValueChanged<int> onCountChanged) {
Firestore.instance
.collection('Notes')
.document('CarNotes')
.collection('PM Overview')
.document(type)
.collection(type)
.getDocuments()
.then((QuerySnapshot snapshot) {
onCountChanged(snapshot.documents.length);
});
});
print(counter);
}
Also, await isn't necessary since you're using then on the Future, and the function inside setState doesn't need to return anything.
The value is still 0, because in your method you are only changing the counter variable inside the method and not the instance variables equipmentCount3. You can create a list to add all the 3 values, and then use that list inside the build method:
int equipmentCount1 = 0;
int equipmentCount2 = 0;
int equipmentCount3 = 0;
List<int> listOfEquipments = List();
void getEquipmentCount(String type, int counter) async {
await Firestore.instance
.collection('Notes')
.document('CarNotes')
.collection('PM Overview')
.document(type)
.collection(type)
.getDocuments()
.then((QuerySnapshot snapshot) {
setState(() {
listOfEquipments.add(snapshot.documents.length);
});
});
}
To add the list to the build method check the following:
https://stackoverflow.com/a/61548797/7015400
Related
Why im getting this error
[VERBOSE-2:ui_dart_state.cc(186)] Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'QueryDocumentSnapshot'
#0 _OpenallsinglehashtagsState.getusers
package:wichtigdenyady/homesearchingall/openalldocs.dart:90
<asynchronous suspension>
I dont know actually why im getting this error maybe anyone can help
Heres where the error throws
List<QueryDocumentSnapshot> _allResults = [];
var firestore = FirebaseFirestore.instance;
QuerySnapshot snapshots = await firestore.collection('videos').get();
for (var doc in snapshots.docs) {
_allResults.add(doc.data()["Hashtagsforallvideos"]);
}
I think maybe it comes from data() because this is dynamic? What I trying here is getting the array from firebase that calls Hashtagsforallvideos which every video in videos collection has.
If you need more information please leave a comment
This is my howle code
class Openallsinglehashtags extends StatefulWidget {
static const route = '/Openallsinglehashtags';
final TextEditingController searchinginput;
const Openallsinglehashtags({Key key, this.searchinginput}) : super(key: key);
#override
_OpenallsinglehashtagsState createState() => _OpenallsinglehashtagsState();
}
class _OpenallsinglehashtagsState extends State<Openallsinglehashtags> {
List <QueryDocumentSnapshot>_allResults = [];
List _resultsList = [];
Future resultsLoaded;
bool nosuerfound = false;
String searchresult;
#override
void initState() {
super.initState();
widget.searchinginput.addListener(_onsearchChanged);
setState(() {
nosuerfound = true;
});
}
#override
void dispose() {
widget.searchinginput.removeListener(_onsearchChanged());
super.dispose();
}
#override
void didChangeDependencies() {
widget.searchinginput.text;
resultsLoaded = getVideos();
super.didChangeDependencies();
}
_onsearchChanged() {
setState(() {
nosuerfound = false;
});
searchResults();
}
searchResults() {
var showResults = [];
if (widget.searchinginput.text != "") {
for (var tripsnapshot in _allResults) {
var title3 = DatbaseService.instance
.videosfromsnapshot(tripsnapshot)
.allhashtagsofeveryvideo
.toLowerCase();
if (title3.contains(widget.searchinginput.text.toLowerCase())) {
setState(() {
nosuerfound = true;
});
showResults.add(tripsnapshot);
}
}
} else {
setState(() {
nosuerfound = true;
});
showResults = List.from(_allResults);
}
setState(() {
_resultsList = showResults;
});
}
Future<List<String>> getVideos() async {
List<String> allVideoHastags = [];
var firestore = FirebaseFirestore.instance;
QuerySnapshot snapshots = await firestore.collection('videos').get();
for (QueryDocumentSnapshot videoSnapshot in snapshots.docs) {
List<String> videoHastags =
List.from(videoSnapshot.data()['Hashtagsforallvideos']);
allVideoHastags.addAll(videoHastags);
}
print(allVideoHastags);
_allResults= snapshots.docs;
searchResults();
return allVideoHastags;
}
#override
Widget build(BuildContext context) {
final user = Provider.of<Userforid>(context);
if (nosuerfound == true) {
return ListView.builder(
itemCount: _resultsList.length,
itemBuilder: (BuildContext context, int index) {
return Container(
margin: const EdgeInsets.all(10.0), // Add margin
child: InkWell(
onTap: () {
NavigationService.instance
.navigateToRoute(MaterialPageRoute(builder: (context) {
return Beitragvideo(
_resultsList[index].data()['Hashtagsforallvideos'],
_resultsList[index].data()['Hashtagsforallvideos'],
_resultsList[index].data()['Hashtagsforallvideos'],
);
}));
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
HighlightedMatchesText(
searchString: widget.searchinginput.text,
content:
_resultsList[index].data()['Hashtagsforallvideos']),
],
),
),
);
},
);
} else {
return Padding(
padding: const EdgeInsets.fromLTRB(0, 30, 0, 0),
child: Center(
child: Container(
child: Text(
"No Hashtag found",
style: TextStyle(fontSize: 16),
)),
),
What I do is I using a searchfield where user can search hashtags. And that hashtags are from the arrays of each video . So what I want is when user typed one hashtags only showing him this hashtags that he enter and not all hashtags of one video and also not all hashtags of the howle list . and if he not searching I just add all hashtags and user can only search in that list if theres no hashtag found then I print no hashtags is found and if any hashtag of that list contains user input I show him these hashtags. HighlightedMatchesText is just a class where I bold these letters that contains user input .
I think we dicussed this on another StackOverflow question. It is not possible to accomplishe what you want. A List<QueryDocumentSnapshot> representing your hashtags because a QueryDocumentSnapshot can only represent a whole firestore document and not just parts/Fields of it.
That means you have 2 options:
Get the whole documents in a list and using QueryDocumentSnapshot like this:
(Your can still read the hastags from the snapshots)
Future<List<QueryDocumentSnapshot>> getVideos() async {
List<QueryDocumentSnapshot> _allResults = [];
QuerySnapshot snapshots = await _firestore.collection('videos').get();
for (QueryDocumentSnapshot videoSnapshot in snapshots.docs) {
_allResults.add(videoSnapshot);
}
return _allResults;
}
Get a List of Strings having all the hashtags without the QueryDocumentSnapshot like this:
Future<List<String>> getHashtags() async {
List<String> allVideoHastags = [];
QuerySnapshot snapshots = await _firestore.collection('videos').get();
for (QueryDocumentSnapshot videoSnapshot in snapshots.docs) {
List<String> videoHastags =
List.from(videoSnapshot.data()['Hashtagsforallvideos']);
allVideoHastags.addAll(videoHastags);
}
return allVideoHastags;
}
If remember correct from your previous question Hashtagsforallvideos was a List<String>?
If this is correct then the values being added to the _allResults will not be QueryDocumentSnapshot as defined by the assignment but rather String, hence the error, _allResults expects a Firebase QueryDocumentSnapshot, but you are adding Strings to the List.
Do let me know if this is true.
Im trying to get data from firebase. But im a bit struggling with that heres how it looks now
getusers() async {
var firestore = FirebaseFirestore.instance;
List listOfIds = [];
QuerySnapshot qn= await firestore
.collection('videos')
.get()
.then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
setState(() {
});
});
});
if (!mounted) return;
_allResults =qn.docs;
What I want is get the hashtasg array field and then add it to the qn.doc data in _allresults . But how can I do that ?
Heres my firebase so you can see how it looks
And last step I wanna loop over the howle hashtag array
This is my widget
class Openalldocs extends StatefulWidget {
final TextEditingController searchinginput;
static const route = '/openalldocs';
const Openalldocs({Key key, this.searchinginput}) : super(key: key);
#override
_OpenalldocsState createState() => _OpenalldocsState();
}
class _OpenalldocsState extends State<Openalldocs> {
List _allResults = [];
List _resultsList = [];
Future resultsLoaded;
bool nosuerfound = false;
String searchresult;
#override
void initState() {
super.initState();
widget.searchinginput.addListener(_onsearchChanged);
setState(() {
nosuerfound = true;
});
}
#override
void dispose() {
widget.searchinginput.removeListener(_onsearchChanged());
super.dispose();
}
#override
void didChangeDependencies() {
widget.searchinginput.text;
resultsLoaded = getusers();
super.didChangeDependencies();
}
_onsearchChanged() {
setState(() {
nosuerfound = false;
});
searchResults();
}
searchResults() {
var showResults = [];
if (widget.searchinginput.text != "") {
for (var tripsnapshot in _allResults) {
var title = DatbaseService.instance
.videosfromsnapshot(tripsnapshot)
.hashtag1
.toLowerCase();
var title2 = DatbaseService.instance
.videosfromsnapshot(tripsnapshot)
.hashtag2
.toLowerCase();
var title3 = DatbaseService.instance
.videosfromsnapshot(tripsnapshot)
.hashtag3
.toLowerCase();
if (title.contains(widget.searchinginput.text.toLowerCase()) ||
title2.contains(widget.searchinginput.text.toLowerCase()) ||
title3.contains(widget.searchinginput.text.toLowerCase())) {
setState(() {
nosuerfound = true;
});
showResults.add(tripsnapshot);
}
}
} else {
setState(() {
nosuerfound = true;
});
showResults = List.from(_allResults);
}
setState(() {
_resultsList = showResults;
});
}
getusers() async {
var firestore = FirebaseFirestore.instance;
List listOfIds = [];
QuerySnapshot qn= await firestore
.collection('videos')
.get()
.then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
setState(() {
_allResults.add(doc.data()["hashtag1"]);
});
});
});
if (!mounted) return;
searchResults();
return "Complete";
}
#override
Widget build(BuildContext context) {
final user = Provider.of<Userforid>(context);
if (nosuerfound == true) {
return ListView.builder(
itemCount: _resultsList.length,
itemBuilder: (BuildContext context, int index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// the AMOUNT is how many hashtags you want to show
for (var i = 0; i < _resultsList.length; i += 1) ...[
// the SizedBox will only exist between the elements in the list
// as before
if (i != 0) SizedBox(height: 6),
// create a builder to allow declaring a variable
Builder(
builder: (context) {
// declare the hashtag variable
final hashtag = 'hashtag${i + 1}';
return InkWell(
onTap: () {
// do something with the hashtag stored in the variable
// this will make it relative to the element in the list
},
child: Column(
children: <Widget>[
// why is there a Column inside another with only one child?
// I would recommend to remove it
Column(
children: [
HighlightedMatchesText(
searchString: widget.searchinginput.text,
// notice how I am using the hashtag variable here
// instead of a constant? ('hashtag1'), by the way
// the for loop will make the hashtag start at 0
// you can change it by increment in the declaration
// `final hashtag = 'hashtag${i+1}'`, if you want
// the existing behavior
content: _resultsList[index][hashtag],
),
],
),
// what is this? if it is to add more space between the items
// in the list, I recommend removing it from here, and add it
// to the first `SizedBox` in the for loop
// in case you do that, the Column that this widget belong
// would also only now contain one widget, so, there is no
// need to have it
SizedBox(height: 3),
],
You are using the Firestore methods correctly, the querySnapshot.docs is an array of all documents in that collection that you are looping through with forEach - You only require further logic on the doc.data().
in this case: push all "hashtag1" to the results
.then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
setState(() {
_allResults.add(doc.data()["hashtag1"]);
});
});
Update Suggested code block
Future<String> getusers() async {
var firestore = FirebaseFirestore.instance;
List listOfIds = [];
QuerySnapshot qn= await firestore
.collection('videos')
.get();
for (var doc in qn.docs) {
setState(() {
_allResults.add(doc.data()["hashtag1"]);
});
}
});
});
if (!mounted) return "Error loading";
searchResults();
return "Complete";
}
yea check out this. if any error, let me no because i am not on system
List<QueryDocumentSnapshot> _allResults =[]
QuerySnapshot qn = await firestore.collection('videos').get();
if (!mounted) return;
setState(() {
_allResults = qn.docs;
});
UPDATE
This line states that the _resultList is a List of documents, and you want to access all the hashtags from it, because you have the for-loop, which goes until it reaches the length of _resultList, therefore you are getting all the hashtags. If you only want to show the hashtag1, then change this:
content: _resultsList[index].data()[hashtag],
to this:
content: _resultsList[index].data()["hashtag1"],
If you want to have all the documents in this List, use this:
.then((QuerySnapshot querySnapshot) {
_allResults = querySnapshot.docs;
}
My problem is that when I receive information from Firestore, I see it in the console that it prints but my UI does not update. But until I press the icon that shows my screen again. The screen where my list of widgets is contained in a BottomNavigationBar.
What I hope will happen with the code is that when I select the tab that will contain my screen in the BottomNavigationBar, the list of Widgets appears with the names of the DocumentIDs. Well, currently I must select the tab again so that they appear.
I attach my code.
class PruebasVarias extends StatefulWidget {
#override
_PruebasVariasState createState() => _PruebasVariasState();
}
class _PruebasVariasState extends State<PruebasVarias> {
List<String> myData = [];
List<Widget> myListWidget = [];
#override
void initState() {
super.initState();
getallDocument();
}
Future getallDocument()async{
final QuerySnapshot result = await Firestore.instance
.collection("Users")
.getDocuments();
final List<DocumentSnapshot> documentos = result.documents;
documentos.forEach((data) {
myData.add(data.documentID);
print(myData);
});
for (int i = 0; i < (myData.length); i++){
myListWidget.add(Text("${myData[i]}"));
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text("Documents"),
actions: <Widget>[
],
),
body: Center(
child:
Column(children: myListWidget),
)
);
}
}
An easy fix : use then to call a callback function and inside callback function use setState to update the UI.
class PruebasVarias extends StatefulWidget {
#override
_PruebasVariasState createState() => _PruebasVariasState();
}
class _PruebasVariasState extends State<PruebasVarias> {
List<String> myData = [];
List<Widget> myListWidget = [];
#override
void initState() {
super.initState();
getallDocument().then(()=>updateUI()).catchError((error)=>print(error));
}
Future<void> getallDocument()async{
final QuerySnapshot result = await Firestore.instance
.collection("Users")
.getDocuments();
final List<DocumentSnapshot> documentos = result.documents;
documentos.forEach((data) {
myData.add(data.documentID);
print(myData);
});
for (int i = 0; i < (myData.length); i++){
myListWidget.add(Text("${myData[i]}"));
}
}
void updateUI()
{
setState((){});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: Text("Documents"),
actions: <Widget>[
],
),
body: Center(
child:
Column(children: myListWidget.isEmpty?[Text("Waiting...")]:myListWidget),
)
);
}
}
You can fix this by calling setState(() {}) method; setState
Notify the framework that the internal state of this object has changed.
Future getallDocument() async {
final QuerySnapshot result =
await Firestore.instance.collection("Users").getDocuments();
final List<DocumentSnapshot> documentos = result.documents;
documentos.forEach((data) {
myData.add(data.documentID);
print(myData);
});
for (int i = 0; i < (myData.length); i++) {
myListWidget.add(Text("${myData[i]}"));
}
setState(() {});
}
I am saving a list of profiles in sqflite and I am trying to make my list reorderable. In my Helper class I have these methods:
static Future insertProfile(Map<String, dynamic> profile) async {
await db.insert('Profiles', profile);
}
static Future deleteProfile(int id) async {
await db.delete('Profiles', where: 'id = ?', whereArgs: [id]);
}
static Future updateProfile(Map<String, dynamic> profile) async {
await db.update('Profiles', profile,
where: 'id = ?', whereArgs: [profile['id']]);
}
My profiles list looks like this:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Profiles')),
body: FutureBuilder(
future: ProfileProvider.getProfileList(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
var profiles = snapshot.data;
return snapshot.data == null
? Container()
: ReorderableListView(
children: List.generate(
profiles.length,
(index) {
return Dismissible(
key: ValueKey("value$index"),
background: slideBackground(),
onDismissed: (direction) {
ProfileProvider.deleteProfile(
profiles[index]['id']);
showSnackBar(
context, profiles[index]['title'], [index]);
},
I am trying to replicate this type of function, but with Sqlite:
void _onReorder(int oldIndex, int newIndex) {
setState(
() {
if (newIndex > oldIndex) {
newIndex -= 1;
}
final String item = profiles.removeAt(oldIndex);
profiles.insert(newIndex, item);
},
);
}
So far I have managed deleting successfully:
onReorder: (int oldIndex, int newIndex) {
if (newIndex > oldIndex) {
newIndex -= 1;
}
setState(
() {
ProfileProvider.deleteProfile(profiles[oldIndex]['id']);
},
);
},
The problem is I can't find how to reinsert the same profile at the new index.
I tried many things but the latest is this:
var item = profiles[oldId]['id'];
ProfileProvider.deleteProfile(profiles[oldId]['id']);
ProfileProvider.insertProfile(item);
However, I get this error message :
type 'int' is not a subtype of type 'Map<String, dynamic>'
Any ideas?
I am trying to paginate in Flutter with firebase realtime databse.
I have tried this in Firestore and it works fine there but I want this with realtime database.
I am fetching data for the first time like this.
Widget buildListMessage() {
return Flexible(
child: StreamBuilder(
stream: _firebase.firebaseDB
.reference()
.child("chats")
.child("nsbcalculator")
.orderByChild('timestamp')
.limitToFirst(15)
.onValue,
builder: (context, AsyncSnapshot<Event> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(themeColor)));
} else {
if (snapshot.data.snapshot.value != null) {
listMessage = Map.from(snapshot.data.snapshot.value)
.values
.toList()
..sort(
(a, b) => a['timestamp'].compareTo(b['timestamp']));
if (lastVisible == null) {
lastVisible = listMessage.last;
listMessage.removeLast();
}
}
return ListView.builder(
...
);
}
},
),
);
}
After that to paginate I am using a listener with ScrollController
void _scrollListener() async {
if (listScrollController.position.pixels ==
listScrollController.position.maxScrollExtent) {
_fetchMore();
}
}
and finally
_fetchMore() {
_firebase.firebaseDB
.reference()
.child("chats")
.child("nsbcalculator")
.orderByChild('timestamp')
.startAt(lastVisible['timestamp'])
.limitToFirst(5)
.once()
.then((snapshot) {
List snapList = Map.from(snapshot.value).values.toList()
..sort((a, b) => a['timestamp'].compareTo(b['timestamp']));
if (snapList.isNotEmpty) {
print(snapList.length.toString());
if (!noMore) {
listMessage.removeLast();
//Problem is here.....??
setState(() {
listMessage..addAll(snapList);
});
lastVisible = snapList.last;
print(lastVisible['content']);
}
if (snapList.length < 5) {
noMore = true;
}
}
});
}
Its working fine as realtime communication but when I try to paginate in _fetchMore() setState is called but it refreshes the state of whole widget and restarts the StreamBuilder again and all data is replaced by only new query. How can I prevent this??
Calling setState will redraw your whole widget and your list view. Now, since you supplying the steam that provides the first page, after redraw it just loads it. To avoid that you could use your own stream and supply new content to it. Then your StreamBuilder will handle the update automatically.
You need to store the full list of your items as a separate variable, update it and then sink to your stream.
final _list = List<Event>();
final _listController = StreamController<List<Event>>.broadcast();
Stream<List<Event>> get listStream => _listController.stream;
#override
void initState() {
super.initState();
// Here you need to load your first page and then add to your stream
...
_list.addAll(firstPageItems);
_listController.sink.add(_list);
}
#override
void dispose() {
super.dispose();
}
Widget buildListMessage() {
return Flexible(
child: StreamBuilder(
stream: listStream
...
}
_fetchMore() {
...
// Do your fetch and then just add items to the stream
_list.addAll(snapList);
_listController.sink.add(_list);
...
}
Try this one
pagination for RealTime list
class FireStoreRepository {
final CollectionReference _chatCollectionReference =
Firestore.instance.collection('Chat');
final StreamController<List<ChatModel>> _chatController =
StreamController<List<ChatModel>>.broadcast();
List<List<ChatModel>> _allPagedResults = List<List<ChatModel>>();
static const int chatLimit = 10;
DocumentSnapshot _lastDocument;
bool _hasMoreData = true;
Stream listenToChatsRealTime() {
_requestChats();
return _chatController.stream;
}
void _requestChats() {
var pagechatQuery = _chatCollectionReference
.orderBy('timestamp', descending: true)
.limit(chatLimit);
if (_lastDocument != null) {
pagechatQuery =
pagechatQuery.startAfterDocument(_lastDocument);
}
if (!_hasMoreData) return;
var currentRequestIndex = _allPagedResults.length;
pagechatQuery.snapshots().listen(
(snapshot) {
if (snapshot.documents.isNotEmpty) {
var generalChats = snapshot.documents
.map((snapshot) => ChatModel.fromMap(snapshot.data))
.toList();
var pageExists = currentRequestIndex < _allPagedResults.length;
if (pageExists) {
_allPagedResults[currentRequestIndex] = generalChats;
} else {
_allPagedResults.add(generalChats);
}
var allChats = _allPagedResults.fold<List<ChatModel>>(
List<ChatModel>(),
(initialValue, pageItems) => initialValue..addAll(pageItems));
_chatController.add(allChats);
if (currentRequestIndex == _allPagedResults.length - 1) {
_lastDocument = snapshot.documents.last;
}
_hasMoreData = generalChats.length == chatLimit;
}
},
);
}
void requestMoreData() => _requestChats();
}
ChatListView
class ChatView extends StatefulWidget {
ChatView({Key key}) : super(key: key);
#override
_ChatViewState createState() => _ChatViewState();
}
class _ChatViewState extends State<ChatView> {
FireStoreRepository _fireStoreRepository;
final ScrollController _listScrollController = new ScrollController();
#override
void initState() {
super.initState();
_fireStoreRepository = FireStoreRepository();
_listScrollController.addListener(_scrollListener);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Flexible(
child: StreamBuilder<List<ChatModel>>(
stream: _fireStoreRepository.listenToChatsRealTime(),
builder: (context, snapshot) {
return ListView.builder(
itemCount: snapshot.data.length,
controller: _listScrollController,
shrinkWrap: true,
reverse: true,
itemBuilder: (context, index) {
...
}
);
}
)
),
);
}
void _scrollListener() {
if (_listScrollController.offset >=
_listScrollController.position.maxScrollExtent &&
!_listScrollController.position.outOfRange) {
_fireStoreRepository.requestMoreData();
}
}
}
ChatModel Class
class ChatModel {
final String userID;
final String message;
final DateTime timeStamp;
ChatModel({this.userID, this.message, this.timeStamp});
//send
Map<String, dynamic> toMap() {
return {
'userid': userID,
'message': message,
'timestamp': timeStamp,
};
}
//fetch
static ChatModel fromMap(Map<String, dynamic> map) {
if (map == null) return null;
return ChatModel(
userID: map['userid'],
message: map['message'],
timeStamp: DateTime.fromMicrosecondsSinceEpoch(map['timestamp'] * 1000),
);
}
}