Android Studio:处理addGeoQueryDataEventListener结果的良好做法

时间:2019-11-30 22:50:02

标签: android mvvm geofirestore

我正在使用Android体系结构组件( Model-View-ViewModel )从 GeoFirestore

获取geoQuery.addGeoQueryDataEventListener()的结果
  

实现'com.github.imperiumlabs:GeoFirestore-Android:v1.5.0'

每个事件都有自己的回调,而我对所有事件都感兴趣。

我还使用BottomNavigationView,这意味着我只有一个活动,而我所有的逻辑都放在片段中。

我首先实现了onDocumentEntered(),如下所示,我意识到,当我导航到下一个活动并返回到调用 MVVM 的上一个活动时,recyclerView会瞬间复制数据。

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);
        }
    }
}

所以我的问题是:如何正确处理每个事件回调的结果?

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

您可以设置一个自定义类来包装数据和事件侦听器的状态,并在LiveData中进行观察。您还可以在ViewModel本身中处理侦听器,以便仅将其添加一次,并在清除ViewModel后将其清除。如果您希望在ViewModel的整个生命周期中保持数据持久,则将数据存储在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, 
    ....
}

您可以按照以下步骤在您的片段中初始化并观察它:

@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);
}