【发布时间】:2020-08-20 17:53:45
【问题描述】:
我正在尝试在我的项目中实现 VMMV 架构,以降低对象之间的耦合度。
我的 Firestore 数据库中有 2 个实体:优惠和用户。
每个优惠都由用户发布。
检索所有优惠后,我想将有关用户的信息(名称、profileImage、描述)添加到 OffersViewModel(以将其绑定到我拥有的 RecicleView)。
问题是在报价被传递到外层之前我无法同步用户个人资料信息的读取(所以我可以将它们绑定到 1 个模型中)
这是我所拥有的:
package com.kaju.activities.workingActivity.Repository;
import android.util.Log;
import androidx.annotation.NonNull;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.firestore.CollectionReference;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.Query;
import com.google.firebase.firestore.QuerySnapshot;
import com.kaju.activities.workingActivity.Model.ProviderOfferModel;
import com.kaju.activities.workingActivity.Model.ProviderProfileModel;
import java.util.List;
public class FirestoreOfferRepository {
//We get the currently linked firebase firestore database
private FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance();
private CollectionReference offersReference = firebaseFirestore.collection("offers");
private OnFirestoreTaskComplete onFirestoreTaskComplete;
public FirestoreOfferRepository(OnFirestoreTaskComplete onFirestoreTaskComplete){
this.onFirestoreTaskComplete = onFirestoreTaskComplete;
}
public void getOffersData(final String annoucementID){
Query offersForAnnoucement = offersReference.whereEqualTo("announcementID", annoucementID);
offersForAnnoucement.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
@Override
public void onComplete(@NonNull Task<QuerySnapshot> task) {
if(task.isSuccessful()){
final List<ProviderOfferModel> newOffers = task.getResult().toObjects(ProviderOfferModel.class);
//We try to get the information for each user
for(final ProviderOfferModel currentOffer : newOffers){
String userID = currentOffer.getUserID();
getUserProfileData(new UserDataCallback() {
@Override
public void userReadDataCallback(ProviderProfileModel currentUser) {
int index = newOffers.indexOf(currentOffer);
newOffers.get(index).setProvider(currentUser);
//This part here is executed only after the loop is over
}
}, userID);
}
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// I want to wait here so the above callBacks are finished
//And we send the data to the outside layers
onFirestoreTaskComplete.offerDataAdded(newOffers);
}else{
onFirestoreTaskComplete.onError(task.getException());
}
}
});
}
public void getUserProfileData(final UserDataCallback userDataCallback, String userID)
{
firebaseFirestore.collection("users").document(userID).get()
.addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if(task.isSuccessful()) {
ProviderProfileModel currentUser = task.getResult().toObject(ProviderProfileModel.class);
userDataCallback.userReadDataCallback(currentUser);
}
}
});
}
public interface OnFirestoreTaskComplete{
void offerDataAdded(List<ProviderOfferModel> offerRepositoryData);
void onError(Exception e);
}
public interface UserDataCallback{
void userReadDataCallback(ProviderProfileModel currentUser);
}
}
我在 YT 上找到了一个教程,它解释了我应该如何从回调中检索数据,但它似乎不起作用(或者我实现得不好)。
我用Logs尝试了一些调试,围绕回调,执行顺序是这样的:
1-Before 循环 -> 列表不变
2-In 循环 -> 列表不变
3-After 循环 -> 列表不变
4-In callBack -> 列表已更改
感谢您对此事的任何帮助!
【问题讨论】:
-
如果你要使用 MVVM,减少耦合。请检查 LiveData。 LiveData 比回调更好。
-
您可以尝试为此使用协程。本质上,您可以使用挂起函数来获取第一个数据,然后等待第二个挂起函数返回其余数据。如果将其与 livedata 结合使用,则不必再使用回调并监听更改。查看文档 [此处][1] [1]:kotlinlang.org/docs/reference/coroutines-overview.html
-
@Abhimanyu 我在外层使用LiveData
-
@MateoHervas Java 也支持这个吗?
标签: java android asynchronous google-cloud-firestore callback