Android Studio:处理addGeoQueryDataEventListener结果的良好做法 [英] Android Studio: Good practice for handling results from addGeoQueryDataEventListener
问题描述
我正在使用Android体系结构组件( Model-View-ViewModel )从 GeoFirestore
I am using Android Architecture Components (Model-View-ViewModel) to get the results from geoQuery.addGeoQueryDataEventListener()
from GeoFirestore
实现'com.github.imperiumlabs:GeoFirestore-Android:v1.5.0'
implementation 'com.github.imperiumlabs:GeoFirestore-Android:v1.5.0'
每个事件都有自己的回调,我对所有事件都感兴趣.
Each event has its own callback and I am interested in all of them.
我也在使用BottomNavigationView
,这意味着我只有一个活动,而我所有的逻辑都放在片段中.
I am also using BottomNavigationView
what means that I only have one activity and all my logic is placed in the fragments.
我首先实现了如下所示的onDocumentEntered()
,我意识到,当我导航到下一个活动并返回到调用 MVVM 的上一个活动时,recyclerView会瞬间复制数据.
I started off by implementing onDocumentEntered()
as shown below and I realized that when I navigate to next activity and get back to the previous one where MVVM is been called, the recyclerView momentaneously duplicates the data.
public class FirestoreGeoQuery extends LiveData<List<StoreModel>> {
private static final String TAG = "debinf FBGeoQuery";
private GeoQuery geoQuery;
private Class clazz;
private List<StoreModel> itemList = new ArrayList<>();
public FirestoreGeoQuery(GeoQuery geoQuery, Class clazz) {
this.geoQuery = geoQuery;
this.clazz = clazz;
}
GeoQueryDataEventListener geoQueryDataEventListener = new GeoQueryDataEventListener() {
@Override
public void onDocumentEntered(@NotNull DocumentSnapshot documentSnapshot, @NotNull GeoPoint geoPoint) {
Log.i(TAG, "onDocumentEntered: "+documentSnapshot);
if (documentSnapshot.exists()) {
StoreModel item = (StoreModel) documentSnapshot.toObject(clazz);
item.setGeoPoint(geoPoint);
Log.i(TAG, "onDocumentEntered: addGeoQueryDataEventListener - store.name: "+item.getName()+", address: "+item.getAddress()+", geoPoint: "+item.getGeoPoint());
itemList.add(item);
}
}
@Override
public void onDocumentExited(@NotNull DocumentSnapshot documentSnapshot) {
Log.i(TAG, "onDocumentExited: ");
}
@Override
public void onDocumentMoved(@NotNull DocumentSnapshot documentSnapshot, @NotNull GeoPoint geoPoint) {
Log.i(TAG, "onDocumentMoved: ");
}
@Override
public void onDocumentChanged(@NotNull DocumentSnapshot documentSnapshot, @NotNull GeoPoint geoPoint) {
Log.i(TAG, "onDocumentChanged: ");
}
@Override
public void onGeoQueryReady() {
Log.i(TAG, "onGeoQueryReady: ");
setValue(itemList);
}
@Override
public void onGeoQueryError(@NotNull Exception e) {
Log.i(TAG, "onGeoQueryError: ");
}
};
@Override
protected void onActive() {
super.onActive();
geoQuery.addGeoQueryDataEventListener(geoQueryDataEventListener);
}
@Override
protected void onInactive() {
super.onInactive();
if (!hasActiveObservers()) {
geoQuery.removeGeoQueryEventListener(geoQueryDataEventListener);
}
}
}
所以我的问题是:如何正确处理每个事件回调的结果?
So my question is: How to properly handle the results from each event callback?
感谢您的帮助!
推荐答案
您可以设置一个自定义类来包装数据和事件侦听器的状态,并在LiveData
中进行观察.您还可以在ViewModel
本身中处理侦听器,以便仅将其添加一次,并在清除ViewModel
后将其清除.如果希望数据在Activity
的整个生命周期中保持不变,则将数据存储在ViewModel
中也是一个好主意.
You can setup a custom class to wrap the data and the status of the event listener and observe it within a LiveData
. You can also handle the listener in the ViewModel
itself so that it's only added once, and cleared once the ViewModel
is cleared. Storing data in your ViewModel
is also a good idea if you want it to persist throughout the lifecycle of your Activity
.
ViewModel
private MutableLiveData<Resource<StoreModel>> data;
private Resource resource;
private List<StoreModel> itemList = new ArrayList<>();
public MyViewModel() {
resource = new Resource();
data = getData();
GeoQueryDataEventListener geoQueryDataEventListener = new GeoQueryDataEventListener() {
@Override
public void onDocumentEntered(@NotNull DocumentSnapshot documentSnapshot, @NotNull GeoPoint geoPoint) {
Log.i(TAG, "onDocumentEntered: "+documentSnapshot);
if (documentSnapshot.exists()) {
StoreModel item = (StoreModel) documentSnapshot.toObject(clazz);
item.setGeoPoint(geoPoint);
data.postValue(resource.onDocumentEntered(item));
}
}
@Override
public void onDocumentExited(@NotNull DocumentSnapshot documentSnapshot) {
Log.i(TAG, "onDocumentExited: ");
data.postValue(resource.onDocumentExited(...));
}
@Override
public void onDocumentMoved(@NotNull DocumentSnapshot documentSnapshot, @NotNull GeoPoint geoPoint) {
Log.i(TAG, "onDocumentMoved: ");
data.postValue(resource.onDocumentMoved(...));
}
@Override
public void onDocumentChanged(@NotNull DocumentSnapshot documentSnapshot, @NotNull GeoPoint geoPoint) {
Log.i(TAG, "onDocumentChanged: ");
data.postValue(resource.onDocumentChanged(...));
}
@Override
public void onGeoQueryReady() {
Log.i(TAG, "onGeoQueryReady: ");
data.postValue(resource.onGeoQueryReady(...));
}
@Override
public void onGeoQueryError(@NotNull Exception e) {
Log.i(TAG, "onGeoQueryError: ");
data.postValue(resource.onGeoQueryError(...));
}
geoQuery.addGeoQueryDataEventListener(geoQueryDataEventListener);
}
@Override
protected void onCleared() {
geoQuery.removeGeoQueryEventListener(geoQueryDataEventListener);
}
public MutableLiveData<Resource<StoreModel>> getData() {
if (data == null) {
data = new MutableLiveData<Resource<StoreModel>>();
}
return data;
}
资源
class Resource {
private Status currentStatus;
private StoreModel item;
public Resource() { }
public Resource onDocumentEntered(StoreModel item) {
this.status = Status.ON_DOCUMENT_ENTERED;
this.item = item;
return this;
}
.... handle other functions
}
状态
enum Status {
ON_DOCUMENT_ENTERED,
ON_DOCUMENT_EXITED,
....
}
您可以初始化&在您的片段中观察它,如下所示:
And you can initialize & observe it in your Fragment as follows:
@Override
protected void onStart() {
// initialize existing data
if (viewModel.getItemList().size() > 0) {
updateUI(data);
}
// observe listener events
observer = new Observer<Resource<List<String>>>() {
@Override
public void onChanged(@Nullable final Resource<List<String>> resource) {
switch(resource.getCurrentStatus()) {
case Status.ON_DOCUMENT_ENTERED:
viewModel.getItemList().add(resource.getItem());
....
break;
case Status.ON_DOCUMENT_EXITED:
...
break;
...
}
}
};
viewModel.getData().observe(this, observer);
}
@Override
protected void onStop() {
viewModel.getData().removeObserver(observer);
}
这篇关于Android Studio:处理addGeoQueryDataEventListener结果的良好做法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!