Создание адаптера в зависимости от положения - PullRequest
0 голосов
/ 08 октября 2019

Я пытаюсь сделать что-то следующим образом:

enter image description here

У меня есть приложение, и я знаю свое местоположение (скажем, это номер 4для примера). У меня также есть определенный радиус. Мне понравилось, что он показывает в адаптере под картой все результаты, которые находятся внутри радиуса (например, он должен показывать только 1 и 5 - 4 - мое местоположение, поэтому мне не нужно его показывать).

Теперь представьте, что числа, которые я пытаюсь показать, это пользователи, которых я имею в своей базе данных Cloud Firestore. Чтобы показать их на карте, мне нужно выполнить запрос, чтобы проверить некоторые условия, а затем также проверить, находятся ли они внутри определенного радиуса. Если они оба имеют условие и находятся внутри радиуса, я хотел, чтобы они были добавлены в адаптер.

Я использую следующий код для его реализации:

db.collection("Users").document(document.getData().get( "UserID" ).toString()).collection( "Location" ).get()
                                .addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                                    @Override
                                    public void onComplete(@NonNull Task<QuerySnapshot> task) {
                                        if (task.isSuccessful()) {
                                            for (QueryDocumentSnapshot document2 : task.getResult()) {

                                                Object BookLat = document2.getData().get( "Lat" );
                                                Object BookLon = document2.getData().get( "Lon" );

                                                float distance = CalculateDistance(Lat, Lon, BookLat, BookLon);

                                                if (distance <=Radius){
                                                    MapPersonAdapter mapPersonAdapter = new MapPersonAdapter( LocationsActivity.this,document.getData().get( "UserID" ).toString(), distance );
                                                    lvPerson.setAdapter( mapPersonAdapter );
                                                    MapPerson mapPerson = MapPerson.Result(document.getData().get( "UserID" ).toString(), distance);
                                                    mapPersonAdapter.add( mapPerson );
                                                    mapPersonAdapter.notifyDataSetChanged();
                                                }

                                            }
                                        } else {
                                            Log.d("ERROR", "Error getting documents: ", task.getException());
                                        }
                                    }
                                });

Здесь начинаются проблемы.

1) Поскольку мне нужно проверять каждый запрос на расстояние, мне нужно добавить один за другим мой адаптер. Это приводит к тому, что я не могу сохранить все результаты в некотором массиве и затем вставить в адаптер (из-за void класса async task).

2) Мне нужно сделать адаптер MapPersonAdapter с переменными в нем (UserID,distance), поскольку внутри viewHolder адаптера мне нужно использовать:

viewHolder.tvPersonName.setText(person.getPersonName( personID )); 

, который определяется в:

public static String getPersonName(String personID) {
    // PART FOR DISPLAYING PROFILE NAME//
    FirebaseFirestore db = FirebaseFirestore.getInstance();
    CollectionReference username = db.collection( "Users" ).document(personID).collection( "UserData" );
    username.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {
                for (QueryDocumentSnapshot document : task.getResult()) {
                    personname = document.getString( "username" );
                }
            } else {
                Log.d(TAG, "Error getting documents: ", task.getException());
            }
        }
    });
    return personname;
}

Это вызывает необходимость инициализации адаптера внутризапрос.

Эти две проблемы вынуждают меня инициализировать адаптер внутри самого запроса, что в конечном итоге приводит к главной проблеме, заключающейся в том, что адаптер показывает только последний результат, поскольку он перезаписывает представления (всегда возвращает позицию 0).

Есть ли способ создать такой адаптер, который вызывается внутри цикла for и в то же время сохраняет все результаты? (Пожалуйста, помните, что это внутри асинхронной задачи, и очень сложно получить результаты вне запроса).

Спасибо

1 Ответ

1 голос
/ 08 октября 2019

Мне понравилось показывать в адаптере под картой все результаты, которые находятся внутри радиуса (например, он должен показывать только 1 и 5 - 4 - мое местоположение, поэтому мне не нужно его показывать).

В настоящее время вы не можете запросить базу данных Cloud Firestore с помощью геолокации. Firestore не поддерживает запросы GeoPoint. Единственный способ решить эту проблему - использовать геохэш . Также есть очень полезное видео , в котором Франк ван Пуффелен подробно объясняет ту же тему.

Кроме того, что если вы используете Android, есть также библиотека с именем Библиотека GeoFirestoreдля Android , который может помочь вам найти ближайшее местоположение в пределах определенного радиуса.

Более того, API-интерфейсы Firebase являются асинхронными, поэтому вы не можете вернуть данные, которые вы получаете из базы данных, в качестве результата метода. Быстрое решение этой проблемы - использовать значение personname только внутри метода onComplete(), в противном случае я рекомендую вам посмотреть последнюю часть моего ответа из этого post в котором я объяснил, как это можно сделать с помощью пользовательского обратного вызова. Вы также можете взглянуть на это видео для лучшего понимания.

...