使 geoQuery.addGeoQueryEventListener() 成为阻塞操作
Make geoQuery.addGeoQueryEventListener() a blocking operation
我为 Firestore 中的每个文档保存了一个包含一些虚拟数据的商店列表和 latitude/longitudes。我想在 poi 附近获取文件。为此,我使用了 GeoFire 库。
现在,我可以从 geoQuery.addGeoQueryEventListener() 方法中对数据进行排序,但此方法不是阻塞操作,因此我的代码在 geoQuery.addGeoQueryEventListener() 可以 return 排序列表之前退出。下面是代码片段:
List<QueryDocumentSnapshot> doc = new ArrayList<>();
List<String> businessIds = new ArrayList<>();
Set<Business> businessSet = new HashSet<>();
GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(latitude, longitude), 2000);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
@Override
public void onKeyEntered(String key, GeoLocation location) {
// TODO Auto-generated method stub
businessIds.add(key);
}
@Override
public void onKeyExited(String key) {
// TODO Auto-generated method stub
}
@Override
public void onKeyMoved(String key, GeoLocation location) {
// TODO Auto-generated method stub
}
@Override
public void onGeoQueryReady() {
// TODO Auto-generated method stub
System.out.println("All initial data has been loaded and events have been fired!");
}
@Override
public void onGeoQueryError(DatabaseError error) {
// TODO Auto-generated method stub
System.err.println("There was an error with this query: " + error);
}
});
geoQuery.removeAllListeners();
ApiFuture<QuerySnapshot> query = firestore.collection("business").whereIn("businessId", businessIds).get();
businessSet = query.get().getDocuments().stream()
.map(b -> b.toObject(Business.class)).collect(Collectors.toSet());
return businessSet;
在上面的代码中,我的程序在 onKeyEntered() 中将键添加到 businessIds 之前退出。
请注意,我不知道您正在使用的那些 API,但理论上,您应该能够使用 CompletableFuture
,例如像这样的东西(未测试):
private CompletableFuture<List<String>> runGeoQuery(double latitude, double longitude) {
CompletableFuture<List<String>> future = new CompletableFuture<>();
GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(latitude, longitude), 2000);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
private final List<String> businessIds = new ArrayList<>();
@Override
public void onKeyEntered(String key, GeoLocation location) {
businessIds.add(key);
}
@Override
public void onKeyExited(String key) {
}
@Override
public void onKeyMoved(String key, GeoLocation location) {
}
@Override
public void onGeoQueryReady() {
future.complete(businessIds);
}
@Override
public void onGeoQueryError(DatabaseError error) {
future.completeExceptionally(error);
}
});
return future;
}
然后,您可以使用#thenApply 或#thenCompose 对结果进行组合,或者您可以简单地使用#get 进行阻塞。
旁注,只要确保阻止适合您的情况即可。一个应该 not 没问题的例子是当线程 运行 此代码来自 HTTP 请求池(例如 Netty 的)时,因为这可能会引起争用并停止您的网络服务器处理新请求。
我为 Firestore 中的每个文档保存了一个包含一些虚拟数据的商店列表和 latitude/longitudes。我想在 poi 附近获取文件。为此,我使用了 GeoFire 库。 现在,我可以从 geoQuery.addGeoQueryEventListener() 方法中对数据进行排序,但此方法不是阻塞操作,因此我的代码在 geoQuery.addGeoQueryEventListener() 可以 return 排序列表之前退出。下面是代码片段:
List<QueryDocumentSnapshot> doc = new ArrayList<>();
List<String> businessIds = new ArrayList<>();
Set<Business> businessSet = new HashSet<>();
GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(latitude, longitude), 2000);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
@Override
public void onKeyEntered(String key, GeoLocation location) {
// TODO Auto-generated method stub
businessIds.add(key);
}
@Override
public void onKeyExited(String key) {
// TODO Auto-generated method stub
}
@Override
public void onKeyMoved(String key, GeoLocation location) {
// TODO Auto-generated method stub
}
@Override
public void onGeoQueryReady() {
// TODO Auto-generated method stub
System.out.println("All initial data has been loaded and events have been fired!");
}
@Override
public void onGeoQueryError(DatabaseError error) {
// TODO Auto-generated method stub
System.err.println("There was an error with this query: " + error);
}
});
geoQuery.removeAllListeners();
ApiFuture<QuerySnapshot> query = firestore.collection("business").whereIn("businessId", businessIds).get();
businessSet = query.get().getDocuments().stream()
.map(b -> b.toObject(Business.class)).collect(Collectors.toSet());
return businessSet;
在上面的代码中,我的程序在 onKeyEntered() 中将键添加到 businessIds 之前退出。
请注意,我不知道您正在使用的那些 API,但理论上,您应该能够使用 CompletableFuture
,例如像这样的东西(未测试):
private CompletableFuture<List<String>> runGeoQuery(double latitude, double longitude) {
CompletableFuture<List<String>> future = new CompletableFuture<>();
GeoQuery geoQuery = geoFire.queryAtLocation(new GeoLocation(latitude, longitude), 2000);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
private final List<String> businessIds = new ArrayList<>();
@Override
public void onKeyEntered(String key, GeoLocation location) {
businessIds.add(key);
}
@Override
public void onKeyExited(String key) {
}
@Override
public void onKeyMoved(String key, GeoLocation location) {
}
@Override
public void onGeoQueryReady() {
future.complete(businessIds);
}
@Override
public void onGeoQueryError(DatabaseError error) {
future.completeExceptionally(error);
}
});
return future;
}
然后,您可以使用#thenApply 或#thenCompose 对结果进行组合,或者您可以简单地使用#get 进行阻塞。
旁注,只要确保阻止适合您的情况即可。一个应该 not 没问题的例子是当线程 运行 此代码来自 HTTP 请求池(例如 Netty 的)时,因为这可能会引起争用并停止您的网络服务器处理新请求。