Java 如何在return语句运行之前等待异步方法完成?
我需要返回语句的Firestore查询结果。该方法返回一个空列表,因为return语句是在任务完成之前运行的 这是我的DatabaseManager类中有问题的代码:Java 如何在return语句运行之前等待异步方法完成?,java,android,firebase,google-cloud-firestore,Java,Android,Firebase,Google Cloud Firestore,我需要返回语句的Firestore查询结果。该方法返回一个空列表,因为return语句是在任务完成之前运行的 这是我的DatabaseManager类中有问题的代码: public List<Image> getImagesFromDatabase(Query query){ List<Image> dataList= new ArrayList<Image>(); query.get().addOnCompleteListener(new
public List<Image> getImagesFromDatabase(Query query){
List<Image> dataList= new ArrayList<Image>();
query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
Image image=document.toObject(Image.class);
image.setDocumentId(document.getId());
dataList.add(image);
}
} else {
Log.d("DatabaseManager", "Error getting documents: ", task.getException());
}
}
});
return dataList;
}
公共列表getImagesFromDatabase(查询){
List dataList=new ArrayList();
query.get().addOnCompletListener(新的OnCompletListener()){
@凌驾
未完成的公共void(@NonNull任务){
if(task.issusccessful()){
对于(QueryDocumentSnapshot文档:task.getResult()){
Image=document.toObject(Image.class);
image.setDocumentId(document.getId());
dataList.add(图像);
}
}否则{
Log.d(“DatabaseManager”,“获取文档时出错:”,task.getException());
}
}
});
返回数据列表;
}
这是使用前面方法返回的列表的代码:
private int getMaxNumberId(){
Query query=dbManager.getCollectionReference().orderBy("numberId", Query.Direction.DESCENDING).limit(1);
List<Image> images=dbManager.getImagesFromDatabase(query);
Image maxImage=images.get(0);
return maxImage.getNumberId();
}
private int getMaxNumberId(){
Query Query=dbManager.getCollectionReference().orderBy(“numberId”,Query.Direction.DESCENDING)。限制(1);
List images=dbManager.getImagesFromDatabase(查询);
图像最大化=图像。获取(0);
返回maxImage.getnumberrid();
}
据我所知,Future不是一个好的解决方案,我读过Future,也读过关于创建回调接口的内容,但由于return语句,我不知道如何实现该解决方案。这段代码面临的问题是它没有以同步方式运行。这基本上意味着它并不是按照读取的方式执行的。
getImagesFromDatabase()
正在做的是:
dataList
变量get()
)并暂时忘记它。数据列表
ArrayListonComplete()
时,您需要一种方法让您的代码知道Firebase已经返回了您的结果,因为现在它所做的唯一事情是将您的结果设置为已返回的过时实例。
在这种情况下,我可以想到三种解决方案
- 等待结果 对于第一个解决方案,Firebase SDK应该提供一个有用的方法来等待您的查询,换句话说,冻结调用它的线程(很可能是UI线程,所以这不是一个好主意)。在搜索了一段时间后,但它似乎给出了不同的结果,这不是推荐的方法,所以让我们继续下一个方法
- 设置回调
- 创建一个接口来表示所需的方法(即onSuccess、onFailure)
- 通过匿名类将所述接口实例化为变量,并将该变量传递给
方法getImagesFromDatabase()
- 在Firebase的
方法中调用变量的方法(即onComplete()
)variable.onSuccess(results)
- 希望调用匿名类中的
实现,在匿名类中,您可能可以使用结果所需的所有资源onSuccess()
有关此项的更多详细信息,请查看
- 使变量
任何可观察
变量都会在发生更改时通知您,只要您对其设置了可观察的
。您可以使用Android的观察者
方法来实现这一点,或者在您的项目中设置了它。这也符合Android关于基于事件的编程、MVVM体系结构的指导原则,一般来说,这将为您的思维省去很多麻烦 您可以将ArrayList转换为,实例化它并按原样返回它。然后,您需要在此变量上设置一个侦听器/观察者,并最终在.observe(lifecycleOwner,Observer{})
中更新其值onComplete()
getMaxNumberId()
),以更具反应性的方式运行。特别是当您与Firebase通信时,要知道您必须以基于事件的方式工作,而不是以具有常见函数返回的顺序方式工作(当然,除非它们是可观察的!)
希望这有帮助,Panos。作为Panos Gr,您可以使用
界面
。首先创建一个新接口,同样的类也可以
private interface IQuery{
void onSuccess(List<Image> imageList);
}
然后在方法getMaxNumberId
private int getMaxNumberId(){
Query query=dbManager.getCollectionReference().orderBy("numberId", Query.Direction.DESCENDING).limit(1);
dbManager.getImagesFromDatabase(query, new IQuery() {
@Override
public void onSuccess(List<Image> imageList) {
Image maxImage=imageList.get(0);
return maxImage.getNumberId();
}
});
Image maxImage=images.get(0);
return maxImage.getNumberId();
}
private int getMaxNumberId(){
Query Query=dbManager.getCollectionReference().orderBy(“numberId”,Query.Direction.DESCENDING)。限制(1);
数据库中的dbManager.getImagesFromDatabase(查询,新IQuery(){
@凌驾
成功时公开作废(列表图像列表){
图像最大值=imageList.get(0);
返回maxImage.getnumberrid();
}
});
图像最大化=图像。获取(0);
返回maxImage.getnumberrid();
}
我希望你会明白这一点这对你有帮助吗:请检查副本,看看你如何解决这个问题。这里有两个答案。第二种方法是使用get()和相应的回调。@AlexMamo,谢谢,这很有效,但这是一个非常混乱的解决方案,至少对我来说是这样,因为我有很多其他代码依赖于get()的结果,因此,所有这些代码都必须在onResponse()中。另一种方法可能是使用Kotlin协程。
private int getMaxNumberId(){
Query query=dbManager.getCollectionReference().orderBy("numberId", Query.Direction.DESCENDING).limit(1);
dbManager.getImagesFromDatabase(query, new IQuery() {
@Override
public void onSuccess(List<Image> imageList) {
Image maxImage=imageList.get(0);
return maxImage.getNumberId();
}
});
Image maxImage=images.get(0);
return maxImage.getNumberId();
}