objectbox-java icon indicating copy to clipboard operation
objectbox-java copied to clipboard

Improve DataObserver reference holding

Open Onheiron opened this issue 7 years ago • 6 comments

I'm trying to use obervable queries to detect when the user is logged in my application in order to start fetching data in background with correct authorization token.

    ...
    userBox.query().build().subscribe().observe(users -> fetchUserData());
    ...
    boxStore.subscribe(User.class).observe(class -> fetchUserData());

First "live" query doesn't work whilst the second works fine whenever I put(user) a new user in the userBox.

Is this correct? I'm not sure from which thread the user is being inserted, might this be an issue? Does it make sense to use a "live" query to observe the insertion of new objects or is it just for changes in existing objects? Live queries would be great, for my application and are the main feature that made me pick ObjectBox, hope I can get it working.

Onheiron avatar Oct 16 '17 13:10 Onheiron

Looks good at a first glance. Did you verify fetchUserData was not called? E.g. by setting a break point?

greenrobot avatar Oct 16 '17 15:10 greenrobot

Yes, I'm logging and setting break points at each step and seems like it gets called only at subscribe time. I'm actually using custom rxJava wrapper with it to have Observable<List<User>> available:

    public Observable<List<User>> getUsersLive() {
        return Observable.create(new ObservableOnSubscribe<List<T>>() {
            @Override
            public void subscribe(@NonNull final ObservableEmitter<List<T>> e) throws Exception {
                userBox.query().build().subscribe().observe(new DataObserver<List<T>>() {
                            @Override
                            public void onData(@NonNull List<T> data) {
           BP    >>>>> Timber.e("NEW DATA");
                                e.onNext(data)
                            }
                });
            }
        }
    }

Onheiron avatar Oct 16 '17 15:10 Onheiron

The only difference to subscribing using boxStore directly is a call to .weak() and .onlyChanges() when the subscription is built. As the second doesn't matter when subscribing to a query (the initial value is always published) I assume it has to be the weak reference.

@Onheiron Can you try keeping a reference to the Query (result of build()) or DataSubscription (result of observer()) instance, for example in a field? -ut

greenrobot-team avatar Oct 17 '17 08:10 greenrobot-team

Thanks! Keeping the reference works, though it's kind of a drag.

Onheiron avatar Oct 17 '17 08:10 Onheiron

I have a similar problem。I also according to the above said, keep to the Query and DataSubscription references. But onData() will only be callback when the application is first started, and there is no callback after the object is added

store = MyAPP.getBoxStore();
box = store.boxFor(RecommendBean.class);
query = box.query().build();
...
query.subscribe()
        .on(AndroidScheduler.mainThread())
        .observer(new DataObserver<List<RecommendBean>>() {
            @Override
            public void onData(List<RecommendBean> data) {
                Log.i(TAG, "Called!!");
                items.addAll(data);
                adapter.notifyDataSetChanged();
            }
        });
...
//After the network request response
box.put(response.list);

Devocy avatar Oct 17 '17 10:10 Devocy

The weak reference was done to avoid leaks. But the reference keeping is also not perfect. Maybe there's a way to combine both. Any thoughts on elegant solution are welcome.

greenrobot avatar Oct 20 '17 08:10 greenrobot