Realm.io [Java] notifications - How to listen for changes only in certain Table?

有些话、适合烂在心里 提交于 2019-12-06 02:05:02

问题


I see this example code in realm java documentation.

public class MyActivity extends Activity {
    private Realm realm;
    // A reference to RealmChangeListener needs to be held to avoid being
    // removed by the garbage collector.
    private RealmChangeListener realmListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      realm = Realm.getDefaultInstance();
      reamlListener = new RealmChangeListener() {
        @Override
        public void onChange() {
            // ... do something with the updates (UI, etc.) ...
        }};
      realm.addChangeListener(realmListener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Remove the listener.
        realm.removeChangeListener(realmListener);
        // Close the realm instance.
        realm.close();
    }
}

I have some database schema contain several tables. Data is always changing in these tables but I have only the one table I need to listen and refresh UI related to this table. I don't want to check is this changes in Realm was exactly in wanted table after any little updating in any other Realm Objects. What best practices can you suggest?


回答1:


Until Realm has fine-grained notifications, I would implement my own notification system either by using ContentObserver, RxJava or your own Observer interfaces.




回答2:


As said Christian RxJava is can help. Though of course is rather a concept that may require major changes in the code than concrete and rapid solution to the problem. In any case Repository pattern for access to our database is good practice. You can use own layer for access to the Realm. In this case you can control query to the Realm and notify observers if data changed.

    public interface RealmRepository {
            <T> Observable<T> get(Class clazz, Func1<RealmQuery, RealmQuery> predicate);
            void storeObject(Class clazz, JSONObject jsonObject);
            void storeObjects(Class clazz, JSONArray jsonArray);
            <T> Observable<T> update(Class clazz, Action0 action);
         }

Using the Realm interface repository allows you to ensure that you are control all requests.

Now you will get Observable<T> object and can notify if data changed.

    public class RealmRepositoryImpl implements RealmRepository {

    Realm realm;
    RealmQueryableCollection realmQueryCollection;

    public RealmRepositoryImpl(Realm realm) {
        this.realm = realm;
        this.realmQueryCollection = new RealmQueryableCollection();
    }

    @Override
    public <T> Observable<T> get(Class clazz, Func1<RealmQuery, RealmQuery> predicate) {
        BehaviorSubject<T> behaviorSubject = BehaviorSubject.create((T) getInner(clazz, predicate));
        realmQueryCollection.add(clazz, predicate, behaviorSubject);
        return behaviorSubject;
    }

    public <T extends RealmObject> RealmResults<T> getInner(Class clazz, Func1<RealmQuery, RealmQuery> predicate) {
        RealmQuery query = realm.where(clazz);
        if (predicate != null)
            query = predicate.call(query);
        return query.findAll();
    }

    @Override
    public void storeObject(Class clazz, JSONObject jsonObject) {
        realm.beginTransaction();
        realm.createOrUpdateObjectFromJson(clazz, jsonObject);
        realm.commitTransaction();
        notifyObservers(clazz);

    }

    @Override
    public void storeObjects(Class clazz, JSONArray jsonArray) {
        realm.beginTransaction();
        realm.createOrUpdateAllFromJson(clazz, jsonArray);
        realm.commitTransaction();
        notifyObservers(clazz);
    }


    @Override
    public <T> Observable<T> update(Class clazz, Action0 action) {
        return (Observable<T>) Observable.create(subscriber -> {
            realm.beginTransaction();
            action.call();
        }).doOnNext(o -> {
            realm.commitTransaction();
            notifyObservers(clazz);
        });
    }

    private void notifyObservers(Class clazz) {
        Observable.from(realmQueryCollection.getQuerables(clazz))
                .subscribe(realmQuerable ->
                        realmQuerable.getSubject().onNext(getInner(clazz, realmQuerable.getPredicate())));
    }
}

When make get query you just save entity (table), predicate (nice rx.functions.Func1) and subject. When you will change the data in the Realm you can get changed data with saved predicate and notify about changes all observers.

Example get query

public Observable<List<Event>> getEvents() {
        return realmRepository.get(Event.class, predicate -> predicate
                        .equalTo("category", "Art")
                        .or()
                        .equalTo("category", "Music"));
    }

In my opinion a reactive approach is a natural solution to this problem.

Full sample code on GitHub you can try to play with the example. At the moment it is not complete solution (no notification unsubscribe, etc), but rather just an idea.



来源:https://stackoverflow.com/questions/32534131/realm-io-java-notifications-how-to-listen-for-changes-only-in-certain-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!