I can't get result of Future - flutter

I have this initState:
#override
void initState() {
super.initState();
_initState();
}
_initState() async {
_geIdsList().then((result) {
_idList = result;
print('result $_idList');
}, onError: (e) {
print('error $e');
});
}
Then there's my function to fetch the IDs from Firestore:
Future<List<String>> _geIdsList() async {
List<String> ids = [];
StreamSubscription stream;
Firestore _firestore = Firestore.instance;
Geoflutterfire geo;
var collectionReference = _firestore.collection('locations');
geo = Geoflutterfire();
var location = new Location();
var pos = await location.getLocation();
var radius = BehaviorSubject<double>.seeded(10.0);
GeoFirePoint center = geo.point(latitude: pos.latitude.toDouble(), longitude: pos.longitude.toDouble());
stream = radius.switchMap((rad) {
return geo.collection(collectionRef: collectionReference).within(
center: center, radius: rad, field: 'position', strictMode: true);
}).listen((List<DocumentSnapshot> documentList) {
Future.forEach(documentList, (DocumentSnapshot documentSnapshot) {
print('document here ... $documentSnapshot' );
print(documentSnapshot.data['id']);
var id = documentSnapshot.data['id'].toString();
ids.add(id);
}).whenComplete(() {
stream.cancel();
print('ids from function $ids');
return ids;
});
});
}
Now _getIdsList() is working fine and the
when complete print('ids from function $ids');
line, prints the IDs List and I'm unable to understand why it doesn't work in my initState. Can anyone tell me what's wrong with my code?

Related

Complex Firebase query with geofire

Query<Map<String, dynamic>> collectionReference
Type: Query<Map<String, dynamic>>
The argument type 'Query<Map<String, dynamic>>' can't be assigned to the parameter type 'CollectionReference<Object?>'.
We are trying to query our task collection and filter it based on topic, status, userid but we are getting the above error.
We are using the Geofire lib along with Firebase
Future<void> fetchTasksNearBy(double lat, double lng) async {
print('getting tasks in location');
GeoFirePoint center = geo.point(latitude: lat, longitude: lng);
double radius = 60; //in km
String field = 'location';
// Reading nearby tasks based on lat, lng parameters
try {
var collectionReference = tasksRef
.where('status', isEqualTo: 'Posted')
.where('ownerId', isNotEqualTo: widget.user!.id)
.where('category.subCategoryId', isEqualTo: widget.subCat);
Stream<List<DocumentSnapshot>> placesStream =
geo.collection(collectionRef: collectionReference).within(
center: center,
radius: radius,
field: field,
strictMode: true,
); // = false includes borderline places
await for (var doclist in placesStream) {
if (doclist.isNotEmpty) {
for (DocumentSnapshot ds in doclist) {
print('${ds.id} ${ds['title']}');
}
} else {
print('Nearby tasks do not exist in the database');
}
}
} catch (e) {
print(e);
}
}

Why is ChangeNotifier updating endlessly

I have 2 data provider classes that extend ChangeNotifier. Within each, there's a function to fetch data and at the end of them, I use notifyListeners() to notify the screens/listeners that the data changed. However, it seems that the listeners start getting notified endlessly instead of once and that creates a loop of reloading, circle indicators that don't go away, and a frozen screen. I don't get it.
Data providers:
class UsersDataProvider extends ChangeNotifier {
UsersDataProvider() : super();
static Map<int, QueryDocumentSnapshot<Object?>> usersMap = {};
Future<void> fetchUsers() async {
final userRef = FirebaseFirestore.instance.collection('users');
final QuerySnapshot result = await userRef.get();
final docs = result.docs.asMap();
usersMap = docs;
print(usersMap.length);
notifyListeners();
}
}
class PostsDataProvider extends ChangeNotifier {
PostsDataProvider() : super();
static Map<int, QueryDocumentSnapshot<Object?>> postsMap = {};
Future<void> fetchPosts() async {
UsersDataProvider.usersMap.forEach((index, resultValue) async {
final postsRef = FirebaseFirestore.instance
.collection('users')
.doc(resultValue.id)
.collection('posts');
final QuerySnapshot postsResult = await postsRef.get();
final postDocs = postsResult.docs.asMap();
postsMap = postDocs;
print('Post map: ${postsMap.length}');
notifyListeners();
});
}
}
Add listeners and reload data:
Future<void> fetchUsersAndPosts(bool initial) async {
if (!initial) {
setState(() {
postsLoading = true;
});
usersDataProvider.fetchUsers();
postsDataProvider.fetchPosts();
}
if (initial) {
usersDataProvider.addListener(() {
print('changed');
setState(() {
fetchUsersAndPosts(false);
});
});
}
if (initial) {
postsDataProvider.addListener(() {
setState(() {
fetchUsersAndPosts(false);
});
});
}
UsersDataProvider.usersMap.forEach((index, value) async {
List<Post> posts = [];
PostsDataProvider.postsMap.forEach((index, value) {
final post = Post.fromJson(value.data() as Map<String, dynamic>);
posts.add(post);
setState(() {});
if (posts.length == PostsDataProvider.postsMap.length) {
setState(() {
postsList = posts;
postsList.sort((a, b) {
return b.date.compareTo(a.date);
});
postsLoading = false;
});
}
});
final profileInfo =
ProfileInfoObject.fromJson(value.data() as Map<String, dynamic>);
Profile profile = Profile(profileInfo, postsList.where((p) => p.uid == value.id).toList());
UserSearchResult user = (UserSearchResult(profile, value.id));
if (usersList.where((u) => u.uid == user.uid).toList().isEmpty) {
setState(() {
usersList.add(user);
});
}
});
setState(() {
postsList.sort((a, b) {
return b.date.compareTo(a.date);
});
});
}

Query with condition isNotEqualTo not work in flutter

I have a problem with the query with the condition isNotEqualTo does not work and does not show the values ​​checked from the condition, note that I tried the condition isNotEqualTo and it worked
What is the problem
_setStream() async {
var pos = await location.getLocation();
double lat = pos.latitude!;
double lng = pos.longitude!;
var ref = await FirebaseFirestore.instance.collection('now')
.where('uid', isNotEqualTo: _user.uid).orderBy('uid');
GeoFirePoint center = geo.point(latitude: lat, longitude: lng);
stream = radius.switchMap((rad) {
var collectionReference = ref;
return geo.collection(collectionRef: collectionReference).within(
center: center, radius: rad, field: 'location', strictMode: true);
});
setState(() {
isLoading = false;
});
stream = geo.collection(collectionRef: ref).within(
center: center, radius: 2000, field: 'location', strictMode: true);
stream!.listen((List<DocumentSnapshot> documentList) {
documentList.forEach((element) {
print("from data .......element");
print(element.data());
final data = element.data() as Map<String, dynamic>;
final GeoPoint point = data['location']['geopoint'];
print("from data .......latitude");
print(point.latitude);
});
});
}
Even though NotEqual query is available in firebase, it was made available late in flutter plugin. The best option is to fetch all to a list and remove unwanted elements from the list

geoflutterfire stream to Future

I have to query the geoflutterfire data with a Stream.
But I would like to use this in a Future in a ChangeNotifierprovider to be able to wait until the Stream has all data.
I never built a Future with a Stream in it before. What do I have to return?
When I don't have a return and just do notifyListeners(), the function runs forever. So I just put in return true.
Is there a better way to do this?
Future<void> fetchPlacesNearBy(double lat, double lng) async {
print("GETTING FIRESTORE PLACES");
GeoFirePoint center = geo.point(latitude: lat, longitude: lng);
double radius = 5; //in km
String field = 'geo_location';
// Reading nearby places based on lat, lng parameters
try {
Stream<List<DocumentSnapshot>> placesStream =
geo.collection(collectionRef: _placesRef).within(
center: center,
radius: radius,
field: field,
strictMode: false,
); // = false includes borderline places
await for (var doclist in placesStream) {
topWikiPlacesAroundUser2 = [];
if (doclist.length > 0) {
for (DocumentSnapshot ds in doclist) {
/// Init place model
WunderkPlace pl = WunderkPlace.fromMap(
ds.data(), ds.get('geo_location.geopoint'));
topWikiPlacesAroundUser2.add(pl);
}
} else {
print('Nearby places do not exist in the database');
}
notifyListeners();
return true;
}
} catch (e) {
print(e);
return false;
}
}

NoSuchMethodError the method was called on Null

in this code below WeatherModel tried to get current location of android phone,
my problem here is once I start runing it show NoSuchMethod Found, and it says reciever is null,
as I tried a lot of debugging just to see where is my problem.
I now understand that my problem is when I create instance of Location() in WeatherModel, longitude and latitude are null, it never gets value and I dont know why...
Sorry for my bad english :(
const apiKey = 'e3653190f2b1d4803287b3074ecfe618';
const apiWeatherURL = 'https://api.openweathermap.org/data/2.5/weather';
class WeatherModel {
Future<dynamic> getLocationWeather() async {
Location location = Location();
NetworkHelper networkHelper = NetworkHelper(
'https://api.openweathermap.org/data/2.5/weather?lat=${location.latitude}&lon=${location.longitude}&appid=$apiKey');
var weatherData = networkHelper.getData();
return weatherData;
}
}
.....
class Location {
double latitude;
double longitude;
Future<void> getCurrentLocation() async {
try {
Position _position = await Geolocator()
.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
longitude = _position.longitude;
print(longitude);
latitude = _position.latitude;
print(latitude);
} catch (e) {
print(e);
}
}
}
.........
class NetworkHelper {
NetworkHelper(this.url);
final url;
Future getData() async {
http.Response response = await http.get(url);
if (response.statusCode == 200) {
var data = jsonDecode(response.body);
print(" Sarkawtua $data");
return data;
} else
print("Error ${response.statusCode} keshay Internet");
}
}
Because you instance fields are not updated, so they are null. You have method for getting current location but it's not fired in getLocationWeather.
Future<dynamic> getLocationWeather() async {
Location location = Location();
await location.getCurrentLocation();
NetworkHelper networkHelper = NetworkHelper(
'https://api.openweathermap.org/data/2.5/weather?lat=${location.latitude}&lon=${location.longitude}&appid=$apiKey');
var weatherData = await networkHelper.getData();
return weatherData;
}
Edit: You also must await networkHelper.getData() method to get not Future Object.