Android Studio:处理addGeoQueryDataEventListener结果的良好做法 [英] Android Studio: Good practice for handling results from addGeoQueryDataEventListener

查看:116
本文介绍了Android Studio:处理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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆