[英]Retrieving Data from FireStore using MVVM Architecture
I am trying to follow Android Architecture principles and would like you implement them on top of my FireStore database. 我正在尝试遵循Android体系结构原则,并希望您在FireStore数据库的顶部实现它们。
Currently I have a repository Class
that handles all my queries with the underlying data. 目前,我有一个存储库Class
,用于处理所有带有基础数据的查询。 I have a Fragment
that requires a Set<String>
of keys from the fields in a document and am wondering what the best approach to retrieve this data is. 我有一个需要从文档中的字段中获取键的Set<String>
的Fragment
,并且想知道检索此数据的最佳方法是什么。 In my previous question Alex Mamo suggested using an Interface
in conjunction with an onCompleteListener
since retrieval of data from Firestore is Asynchronous
. 在我之前的问题中, Alex Mamo建议将Interface
与onCompleteListener
结合使用,因为从Firestore检索数据是Asynchronous
。
This approach seems to work but I am unsure of how to extract the data from this Interface
to a variable local to my Fragment
. 这种方法似乎有效,但是我不确定如何从此Interface
提取数据到Fragment
局部变量。 If I wish to use this data would my code have to be within my definition of the abstract
method? 如果我想使用这些数据,我的代码是否必须在我对abstract
方法的定义之内?
Am I still following MVVM principle if to get the data from Firestore to my Fragment
I have to pass an Interface
object defined in a Fragment as a parameter to my repository? 如果要将数据从Firestore获取到我的Fragment
我是否仍要遵循MVVM原理,我必须将片段中定义的Interface
对象作为参数传递给我的存储库?
Is this the recommended approach for querying a Firestore database using a Repository? 这是使用存储库查询Firestore数据库的推荐方法吗?
Below is my Interface
and method that calls on a ViewModel
to retrieve data: 以下是调用ViewModel
检索数据的Interface
和方法:
public interface FirestoreCallBack{
void onCallBack(Set<String> keySet);
}
public void testMethod(){
Log.i(TAG,"Inside testMethod.");
mData.getGroups(new FirestoreCallBack() {
//Do I have to define what I want to use the data for here (e.g. display the contents of the set in a textview)?
@Override
public void onCallBack(Set<String> keySet) {
Log.i(TAG,"Inside testMethod of our Fragment and retrieved: " + keySet);
myKeySet = keySet;
Toast.makeText(getContext(),"Retrieved from interface: "+ myKeySet,Toast.LENGTH_SHORT).show();
}
});
}
My ViewModel
method to call on the Repository: 我在存储库上调用的ViewModel
方法:
private FirebaseRepository mRepository;
public void getGroups(TestGroupGetFragment.FirestoreCallBack firestoreCallBack){
Log.i(TAG,"Inside getGroups method of FirebaseUserViewModel");
mRepository.getGroups(firestoreCallBack);
}
Finally my Repository method to query
my FireStore database: 最后,我的Repository方法query
我的FireStore数据库:
public void getGroups(final TestGroupGetFragment.FirestoreCallBack firestoreCallBack){
Log.i(TAG,"Attempting to retrieve a user's groups.");
userCollection.document(currentUser.getUid()).get().addOnCompleteListener(
new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()){
DocumentSnapshot document = task.getResult();
Log.i(TAG,"Success inside the onComplete method of our document .get() and retrieved: "+ document.getData().keySet());
firestoreCallBack.onCallBack(document.getData().keySet());
} else {
Log.d(TAG,"The .get() failed for document: " + currentUser.getUid(), task.getException());
}
}
});
Log.i(TAG, "Added onCompleteListener to our document.");
}
EDITED 已编辑
public void testMethod(){
Log.i(TAG,"Inside testMethod.");
mData.getGroups(new FirestoreCallBack() {
@Override
public void onCallBack(Set<String> keySet) {
Log.i(TAG,"Inside testMethod of our Fragment and retrieved: " + keySet);
myKeySet = keySet;
someOtherMethod(myKeySet); //I know I can simply pass keySet.
Toast.makeText(getContext(),"GOT THESE FOR YOU: "+ myKeySet,Toast.LENGTH_SHORT).show();
}
});
Log.i(TAG,"In testMethod, retrieving the keySet returned: "+ myKeySet);
}
Instead of interface
I only use LiveData
to bring the data to a recyclerview, for example. 例如,我只使用LiveData
而不是interface
将数据带到recyclerview。
First, We have to create our Firestore query
. 首先,我们必须创建Firestore query
。 In this example, I am listing all documents inside a collection. 在此示例中,我列出了集合中的所有文档。
public class FirestoreLiveData<T> extends LiveData<T> {
public static final String TAG = "debinf firestore";
private ListenerRegistration registration;
private CollectionReference colRef;
private Class clazz;
public FirestoreLiveData(CollectionReference colRef, Class clazz) {
this.colRef = colRef;
this.clazz = clazz;
}
EventListener<QuerySnapshot> eventListener = new EventListener<QuerySnapshot>() {
@Override
public void onEvent(@Nullable QuerySnapshot queryDocumentSnapshots, @Nullable FirebaseFirestoreException e) {
if (e != null) {
Log.i(TAG, "Listen failed.", e);
return;
}
if (queryDocumentSnapshots != null && !queryDocumentSnapshots.isEmpty()) {
List<T> itemList = new ArrayList<>();
for (DocumentSnapshot snapshot : queryDocumentSnapshots.getDocuments()) {
T item = (T) snapshot.toObject(clazz);
itemList.add(item);
Log.i(TAG, "snapshot is "+snapshot.getId());
}
setValue((T) itemList);
}
}
};
@Override
protected void onActive() {
super.onActive();
registration = colRef.addSnapshotListener(eventListener);
}
@Override
protected void onInactive() {
super.onInactive();
if (!hasActiveObservers()) {
registration.remove();
registration = null;
}
}
}
Next, we create a link in our Repository
接下来,我们在Repository
创建一个链接
public class Repository {
public Repository() {
}
public LiveData<List<ProductsObject>> productListening(GroupObject group) {
return new FirestoreLiveData<>(DatabaseRouter.getCollectionRef(group.getGroupCreator()).document(group.getGroupKey()).collection("ProductList"), ProductsObject.class);
}
}
After that, we create our ViewModel
: 之后,我们创建ViewModel
:
public class MyViewModel extends ViewModel {
Repository repository = new Repository();
public LiveData<List<ProductsObject>> getProductList(GroupObject groupObject) {
return repository.productListening(groupObject);
}
}
And finally, in our MainActivity
or Fragment
we observe the data contained in ou Firestore: 最后,在我们的MainActivity
或Fragment
我们观察到Firestore中包含的数据:
viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
viewModel.getProductList(groupObject).observe(this, new Observer<List<ProductsObject>>() {
@Override
public void onChanged(@Nullable List<ProductsObject> productsObjects) {
//Log.i(TAG, "viewModel: productsObjects is "+productsObjects.get(0).getCode());
adapter.submitList(productsObjects);
}
});
I hope it helps. 希望对您有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.