背景:我有一个字符串列表,其中包含不同的地点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'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>
。
我通过使用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);