Я делаю флаттер-приложение и использую облачный магазин в качестве своей онлайн-базы данных. Одна из функций моего приложения — поиск ближайших пользователей и отображение их профиля текущему пользователю в пользовательском виджете на экране. Как я это делаю, я получаю текущее местоположение пользователя (либо текущее местоположение, либо адрес, сохраненный в базе данных), а затем просматриваю каждого отдельного пользователя в моей коллекции базы данных для пользователей. Я получаю адрес пользователя из сохраненных данных, рассчитываю расстояние с помощью API матрицы расстояний, а затем, если расстояние меньше определенного числа (например, 10000 метров), я создаю виджет профиля, чтобы пользователь отображал его на экране.
Есть 2 проблемы:
1- если количество моих пользователей растет (например, миллион пользователей), просматривая каждую информацию о пользователе и вычисляя расстояние, может потребоваться очень много времени, чтобы получить результаты на экране. Прямо сейчас у меня есть только 20 пользователей для целей тестирования, и когда я ищу ближайших пользователей, результаты отображаются на экране через 30 секунд.
2- При медленном подключении к Интернету время ожидания может быть намного больше, и для этой простой задачи может потребоваться много пользовательских данных.
Как я могу улучшить эту функцию и сделать ее быстрее?
(Текущая идея, которая у меня есть, состоит в том, чтобы разделить пользователей в разных документах по их местоположению, а затем просмотреть только один из документов, используя текущее местоположение пользователя. Проблема заключается в том, как эффективно разделить адреса и найти лучшие адреса для поиска. за.)
Ниже приведен код, в котором я нахожу ближайших пользователей и добавляю их в список, который я передаю в свой собственный класс виджетов.
final List<UserBoxDesign> listOfBoxes = [];
final FirebaseUser currentUser = await auth.currentUser();
final String currentUserId = currentUser.uid;
if (_userLocationSwitchValue == false) { //use default address of the user
currentUserAddress = await _databaseManagement.getUserCollectionValues(
currentUserId, "address");
} else {
//currentUserAddress = //to do, get device location here.
}
if (_searchValue == SearchValues.Users) {
final List<String> userIds = await _databaseManagement.getUserIds();
for (String id in userIds) {
final String otherUserLocations =
await _databaseManagement.getUserCollectionValues(id, "address");
final String distanceMeters = await _findDistanceGoogleMaps(
currentUserAddress, otherUserLocations);
if (distanceMeters == "Address can't be calculated" ||
distanceMeters == "Distance is more than required by user") {
//if it's not possible to calculate the address then just don't do anything with that.
} else {
final double distanceValueInKilometers = (double.parse(
distanceMeters) /
1000)
.roundToDouble();
final String userProfileImageUrl =
await _databaseManagement.getUserCollectionValues(id, "image");
final String username =
await _databaseManagement.getUserCollectionValues(id, "username");
listOfBoxes.add(
UserBoxDesign( //it creates a custom widget for user if user is nearby
userImageUrl: userProfileImageUrl,
distanceFromUser: distanceValueInKilometers,
userId: id,
username: username,
),
); //here we store the latest values inside the reserved data so when we create the page again, the value will be the reservedData value which is not empty anymore
}
print(listOfBoxes);
}
listOfBoxes.sort((itemA,itemB)=>itemA.distanceFromUser.compareTo(itemB.distanceFromUser)); //SORTs the items from closer to more far from user (we can reverse it to far comes first and close goes last)
setState(() {
_isSearchingForUser = false;
});
return listOfBoxes;
Вот код, в котором я вычисляю расстояние между адресом отправления и адресом назначения.
Future<String> _findDistanceGoogleMaps(
String originAddress, String destinationAddress) async {
final String url =
"https://maps.googleapis.com/maps/api/distancematrix/json?units=metric&origins=$originAddress&destinations=$destinationAddress&key=$GoogleMapsAPIKey";
try {
final response = await http.get(url);
final responseDecoded = json.decode(response.body);
final distanceInMeters = double.parse(responseDecoded["rows"][0]
["elements"][0]["distance"]["value"]
.toString()); //this is the value in meters always so for km , divide by 1000.
if (distanceInMeters < 100000) {
return distanceInMeters.toString();
} else {
return "Distance is more than required by user";
}
} catch (e) {
return "Address can't be calculated";
}
}
так выглядит мой экран, когда я нахожу пользователей поблизости.