在New Places SDK Client中查找PendingResult等效()等效项

问题描述 投票:2回答:2

背景:我有一个字符串列表,其中包含不同的地点ID。一旦用户选择了他的位置,我就会执行一个循环并确定列表中的每个位置(我从位置ID获取位置)是否在他选择的位置附近。我能够使用旧的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}

正如您在上面的代码中看到的那样,旧的PLACES SDK API有一个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不是这种情况。因此,使用新的迁移代码,即使fetchPlace尚未完成获取每次迭代的结果,for循环也会继续并完成循环。因此,代码被破坏,无法获得所需的结果。

有没有办法阻止代码移动直到fetchPlace完成?!

google-places-api google-places
2个回答
3
投票

据我所知,Google's Task API可以等待任何Google API任务。

例如,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>


1
投票

我通过使用Task Class解决了这个问题。见下文:

 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 = placesClient.fetchPlace(request);

FetchPlaceResponse response = Tasks.await(task);

© www.soinside.com 2019 - 2024. All rights reserved.