dart_meteor
dart_meteor copied to clipboard
listen collection
can i convert result of Map<String, dynamic> from listen collection into List?
The meteor.collection('') returns Stream<Map<String, dynamic>> which you can then able to use with the Flutter's StreamBuilder.
If you print it out you will see the format of returning object is:
{
'id1': Map<String, dynamic>,
'id2': Map<String, dynamic>,
...
}
To get the list from that you can do:
meteor.collection('messages').listen((result) {
var listOfMessages = result.values.toList();
}
or with the StreamBuilder
StreamBuilder<Map<String, dynamic>>(
stream: meteor.collection('messages'),
builder: (BuildContext context, AsyncSnapshot<Map<String, dynamic>> snapshot) {
if (snapshot.hasData) {
var listOfMessages = snapshot.data.values.toList();
...
...
Thanks @tanutapi , but I have a problem.. i've listen to the collection in initState but if the app is opened it has a few seconds delay to receive data. how can i add loading before receive data?
void initState() {
super.initState();
meteor.collection('locations').listen((data) {
storeList = data.values.toList();
isLoading = false;
});
}
isLoading still true..
You could share your full widget code if it is possible.
Sure,
class ProductPotrait extends StatefulWidget {
ProductPotrait({Key? key}) : super(key: key);
@override
_ProductPotraitState createState() => _ProductPotraitState();
}
class _ProductPotraitState extends State<ProductPotrait> {
late SubscriptionHandler _subscriptionHandler;
bool isLoading = true;
late List storeList;
@override
void initState() {
super.initState();
_subscriptionHandler = meteor.subscribe('stores.all');
meteor.collection('locations').listen((data) {
storeList = data.values.toList();
isLoading = false;
});
}
@override
void dispose() {
super.dispose();
_subscriptionHandler.stop();
}
@override
Widget build(BuildContext context) {
return Container(
child: isLoading
? Loading()
: Container(),
);
}
}
- Do you forget to use
setState()in your listening function? You should do:
meteor.collection('locations').listen((data) {
setState(() {
storeList = data.values.toList();
isLoading = false;
});
});
- I would suggest you use the StreamBuilder when you build your widget rather than do it in the
initState.
Widget build(BuildContext context) {
return StreamBuilder(
stream: meteor.collection('locations'),
builder: (context, AsyncSnapshot<Map<String, dynamic>> snapshot) {
if (snapshot.hasData) {
var storeList = snapshot.data.values.toList();
return YourAnyStoreListWidget(storeList);
}
return Loading();
},
);
}
ah, maybe I like solution number 2, coz number 1 will triggered memory leak
how about 2 collection listen? @tanutapi
meteor.collection('category').listen((data) {
setState(() {
category = data.values.toList();
});
});
meteor.collection('locations').listen((data) {
if(category.length > 0){
setState(() {
storeList = data.values.toList();
});
}
});
On solution number 1, you must stop listening on your widget dispose().
Cloud you try Rx.combineLatest2 as described in https://stackoverflow.com/questions/55285903/dartlang-rxdart-merge-different-type-streams?
Something like
import 'package:rxdart/rxdart.dart';
...
...
_sub = Rx.combineLatest2(
meteor.collection('category'), meteor.collection('locations'), (category, locations) {
return [category, locations];
}).listen((combine) {
setState(() {
final category = (combine[0] as Map<String, dynamic>).values.toList();
final locations = (combine[1] as Map<String, dynamic>).values.toList();
});
});
...
...
_sub.cancel();