Ищем PendingResult эквивалент await () в клиенте New Places SDK - PullRequest
0 голосов
/ 30 января 2019

Фон: у меня есть список строк, который содержит различные идентификаторы мест.Как только пользователь выбрал свое местоположение, у меня есть цикл, который выполняется и определяет, находится ли каждое место в списке (я получаю местоположение по идентификатору места) рядом с его выбранным местоположением.Я смог реализовать это с помощью старого Places SDK, но не смог перенести его на новый SDK, поскольку кажется, что новый SDK не имеет эквивалента await ().

Вот мой старый код:

   // contains a list of Offices. Has method getId() which contains the Place ID from Google.
    List<Office> results = obtained from the database...

   // go thru each Location and find those near the user's location
        for (int i = 0; i < results.size(); i++) {
            // Get the place from the placeID
            PendingResult<PlaceBuffer> placeResult = Places.GeoDataApi.
                    getPlaceById(mGoogleApiClient, results.get(i).getId());

            // wait for the result to come out (NEED EQUIVALENT IN NEW PLACES SDK)
            PlaceBuffer places = placeResult.await();

            // Get the latitude and longitude for the specific Location
            LatLng latLng = places.get(0).getLatLng();

            // Set the location object for the specific business
            Location A = new Location("Business");
            A.setLatitude(latLng.latitude);
            A.setLongitude(latLng.longitude);
            // get the distance of the business from the user's selected location
            float distance = A.distanceTo(mSelectedLocation);

            // if the distance is less than 50m away
            if (distance < 50) { ... do something in code}

Как видно из кода выше, старый API PLACES SDK имеет класс PendingResult с await () в качестве одного из методов.Это await () в соответствии с блоками документации, пока задача не будет завершена. В РЕЗЮМЕ, код не будет продолжаться, пока не будет получен результат из getPlaceById.

Я перенесен в новый Places SDK согласно документации, и у меня естьпроблемы.Вот мой новый перенесенный код, основанный на документации Google: https://developers.google.com/places/android-sdk/client-migration#fetch_a_place_by_id

         for (int i = 0; i < results.size(); i++) {

            // Get the place Id
            String placeId = results.get(position).getId();
            // Specify the fields to return.
            List<Place.Field> placeFields = Arrays.asList(Place.Field.ID, Place.Field.NAME,
                    Place.Field.LAT_LNG, Place.Field.ADDRESS);
            // Construct a request object, passing the place ID and fields array.
            FetchPlaceRequest request = FetchPlaceRequest.builder(placeId, placeFields)
                    .build();

            // Add a listener to handle the response.
            placesClient.fetchPlace(request).addOnSuccessListener((response) -> {

                    Place place = response.getPlace();

                    // Get the latitude and longitude for the specific location
                    LatLng latLng = place.getLatLng();

                    // Set the location object for the specific business
                    Location A = new Location("Business");
                    A.setLatitude(latLng.latitude);
                    A.setLongitude(latLng.longitude);

                    // get the distance of the business from the selected location
                    float distance = A.distanceTo(mSelectedLocation);

            // if the distance is less than 50m away
            if (distance < 50) { ... do something in code}

Кажется, что ключевая проблема здесь заключается в том, что в старом коде await () блокирует код до его успешного завершения, поэтому цикл for выполняетне процесс.Однако это не относится к OnSuccessListener.В результате с новым перенесенным кодом цикл for продолжается и завершает цикл, даже когда fetchPlace еще не завершил получение своих результатов для каждой итерации.Таким образом, код не работает и не может получить необходимые результаты.

Есть ли способ заблокировать код для перемещения до завершения fetchPlace?!

Ответы [ 2 ]

0 голосов
/ 17 февраля 2019

Насколько мне известно, любая задача Google API может ожидаться API задач Google .

Например, findAutocompletePredictions возвращает объект Task<>.Вместо добавления onCompleteListener вы можете передать эту задачу на Tasks.await.

Вместо этого неблокирующего способа:

OnCompleteListener<T> onCompleteListener= 
    new OnCompleteListener<T> {...}

placesClient.findAutocompletePredictions(f)
    .addOnCompleteListener(onCompleteListener);

Вы можете передать его на Tasks.await()и сделайте блокировку вызовов API:

T results = null;
try {

    // No timeout
    results = Tasks.await(placesClient.findAutocompletePredictions(f));

    // Optionally, with a 30 second timeout:
    results = Tasks.await(
        placesClient.findAutocompletePredictions(f), 30, TimeUnit.SECONDS);

} catch (ExecutionException e) {
    // Catch me
} catch (TimeoutException e) {
    // Catch me, only needed when a timeout is set
} catch (InterruptedException e) {
    // Catch me
}

if (results != null) {
    // Do something
} else {
    // Do another thing
}

По сути, вместо получения PendingResult по умолчанию вы получаете Task<T>, который вы можете использовать, однако.

0 голосов
/ 30 января 2019

Я решил проблему с помощью класса задач.См. Ниже:

 for (int position = 0; position < results.size(); position++) {
            // Get the placeID 
            String placeId = results.get(position).getAddress();

            // Specify the fields to return.
            List<Place.Field> placeFields = Arrays.asList(Place.Field.ID, Place.Field.NAME,
                    Place.Field.LAT_LNG, Place.Field.ADDRESS);

            // Construct a request object, passing the place ID and fields array.
            FetchPlaceRequest request = FetchPlaceRequest.builder(placeId, placeFields)
                    .build();

            // create a FetchPlaceResponse task
            Task<FetchPlaceResponse> task = placesClient.fetchPlace(request);

            try {
                FetchPlaceResponse response = Tasks.await(task);
                Place place = response.getPlace();

                // Get the latitude and longitude for the specific place
                LatLng latLng = place.getLatLng();

                // Set the location object for the specific business
                Location A = new Location("Business");
                A.setLatitude(latLng.latitude);
                A.setLongitude(latLng.longitude);

                // get the distance of the business from the selected location
                float distance = A.distanceTo(mSelectedLocation);

Эти два кода попросят систему дождаться ответа.

Task task = placeClient.fetchPlace (request);

FetchPlaceResponse response= Tasks.await (задача);

...