Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change listener not being triggered on realm updates #1676

Closed
Wattos opened this issue Oct 26, 2015 · 20 comments
Closed

Change listener not being triggered on realm updates #1676

Wattos opened this issue Oct 26, 2015 · 20 comments
Assignees
Labels
Blocked This issue is blocked by another issue T-Bug

Comments

@Wattos
Copy link

Wattos commented Oct 26, 2015

According to the documentation:

"If you want to be notified when the query completes and the RealmResults is updated, you can register a RealmChangeListener. This listener will be called every time the RealmResults is updated to reflect the latest changes in the Realm (usually after a commit)"

I add a change listener to either a RealmObject or RealmResult, but that only gets triggered once (after the data is loaded). The documentation states that this listener should also be triggered when the real result is updated. That does not seem to be the case.

Is the documentation incorrect or do I need to do something special besides commiting a transaction so that the listener gets triggered?

@cmelchior
Copy link
Contributor

Hi @Wattos
The ChangeListener should be triggered on each update, not only when the data is loaded. If this isn't happening it sounds like a bug.

@nhachicha
Copy link
Collaborator

Hi @Wattos
It would be helpful if you can send us some code to reproduce this (either here or privately to help@realm.io)
Cheers,

@nhachicha nhachicha self-assigned this Oct 27, 2015
@Wattos
Copy link
Author

Wattos commented Oct 27, 2015

@nhachicha Do you think that the code is really necessary? I did a quick search in the realm-java repository and the notifyChangeListener method is only called 3 times.

(See https://github.com/realm/realm-java/search?utf8=%E2%9C%93&q=notifyChangeListeners)

None of these method calls would indicate that the change listeners are called on updates in realm

@kneth kneth removed the Pending label Oct 28, 2015
@vikas-fueled
Copy link

I have encountered similar issue with when at times change listener is not being triggered even once for the same query, but is triggered when I query it again. isLoaded returns false in both cases on checking on same thread after registering listener.

public void fetchEpisodes(long seasonId) {
        logger.debug("fetch episodes for Season id :" + seasonId);
        final Realm realm = Realm.getDefaultInstance();
        RealmQuery<Content> query = realm.where(Content.class)
                .equalTo("season.id", seasonId);
        final RealmResults<Content> contents = query
                .findAllAsync();
        contents.addChangeListener(new RealmChangeListener() {
            @Override
            public void onChange() {
                logger.debug("Episodes size :" + contents.size());
                if (adapter != null) {
                    adapter.setEpisodes(contents, coverHandlerProvider);
                }
            }
        });
        logger.debug("Sync Episodes size :" + contents.size() + ", is Loaded :" + contents.isLoaded());
    }

@vikas-fueled
Copy link

From this discussion seems like anonymous listeners should be fine for RealmResults. However when I changed my listener to a concrete one, the above issue was solved. So, this might help in investigating further.

@cmelchior
Copy link
Contributor

@Wattos I tried to reproduce your case, and it looks like it is working as intended. If you can provide some sample code where this is not happening it would be really helpfull.

@kneth kneth added the Pending label Oct 30, 2015
@fuwaneko
Copy link

fuwaneko commented Nov 1, 2015

I have the similar problem and I'm pretty sure it happens only with queries on related models, i.e. .equalsTo("related.id", id). RealmResults is never updated. Listener actually fires twice (first immediately after findAllAsync I guess, second time after data has been written to Realm from network thread), but no data is present in RealmResults! After something else updates Realm, listener fires again and data appears. But, if I remove condition on related model, everything works as it should.

@cmelchior
Copy link
Contributor

@Wattos I discovered that you are right. It seems that our change listeners doesn't get triggered for our synchronous queries and objects. I have updated #1696 with the unit tests to catch this. /cc @nhachicha

@fuwaneko
Copy link

fuwaneko commented Nov 2, 2015

@cmelchior I've created test app to showcase my problems: https://dl.dropboxusercontent.com/u/11334864/master.zip

@nhachicha
Copy link
Collaborator

fixed in 0.87.1

@nhachicha nhachicha removed the P1 label Dec 23, 2015
@jemshit
Copy link

jemshit commented Nov 5, 2016

This issue still exists in Version (io.realm:realm-gradle-plugin:1.1.0) and probably in latest version too. I can reproduce issue, but it is a bit complex.

I have this method which is called by background thread by this lib:

public void saveImageDownloaded(boolean isDownloaded){
        RealmManager realmManager = null;
        try{
            realmManager=new RealmManager();
            realmManager.updateImageDownloaded(isDownloaded,imageDatabaseType, imageName);
        }finally {
            if(realmManager!=null)realmManager.close();
        }
    }

RealmManager.java:

...
realm=Realm.getDefaultInstance();
...
public void updateImageDownloaded(...) {
    realm.executeTransactionAsync(new Realm.Transaction() {
                    @Override
                    public void execute(Realm bgRealm) {
                        ModelRealm_ImageDestination model = bgRealm.where(ModelRealm_ImageDestination.class)
                                .equalTo("imageName", imageName)
                                .findFirst();
                        if (model != null)
                            model.setDownloaded(isDownloaded);
                    }
                });
}
...
public void close() {        
        if (realm != null) {
            realm.close();
        }
}

Problem occurs in exact above calling order, which is not quite right, because i run async call in try block and call realm.close() right after in finally block.

Problem does not occur in this case:

public void saveImageDownloaded(boolean isDownloaded){
        RealmManager realmManager = null;
        try{
            realmManager=new RealmManager();
            realmManager.updateImageDownloaded(isDownloaded,imageDatabaseType, imageName);
        }finally {
            ///if(realmManager!=null)realmManager.close();
        }
    }

Problem does not occur in this case

public void saveImageDownloaded(boolean isDownloaded){
        RealmManager realmManager = null;
        try{
            realmManager=new RealmManager();
            //realmManager.updateImageDownloaded(isDownloaded,imageDatabaseType, imageName);
        }finally {
            if(realmManager!=null)realmManager.close();
        }
    }

@Zhuinden
Copy link
Contributor

Zhuinden commented Nov 5, 2016

You should consider closing the Realm instance only AFTER the transaction is completed

http://stackoverflow.com/a/35402728/2413303

@jemshit
Copy link

jemshit commented Nov 5, 2016

I am aware of close() is called too early, so it should give error like "realm cannot be used after realm instance is closed.." if async op tries to do sth after .close(). But this above code breaks my RealmManager in every screen, even if i create new realm instance and try to use it.

I corrected my method like this:

public void saveImageDownloaded(boolean isDownloaded){

        new Thread(new Runnable() {
            @Override
            public void run() {
                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);

                RealmManager realmManager = null;
                try{
                    realmManager=new RealmManager();
                    realmManager.updateImageDownloadedSynch(isDownloaded,imageDatabaseType, imageName);
                }finally {
                    if(realmManager!=null)realmManager.close();
                }
            }
        }).start();
    }

updateImageDownloadedSynch() is synchronous call on realm instance now, so no problem.

My point is above buggy code should break only one screen, but it breaks whole app until i restart

@Zhuinden
Copy link
Contributor

Zhuinden commented Nov 5, 2016

Define "breaks whole app until restart"

@jemshit
Copy link

jemshit commented Nov 6, 2016

realm.getDefaultInstance() does not work in any screen, for .findAllAsync(), changeListener does not get notified

@Zhuinden
Copy link
Contributor

Zhuinden commented Nov 6, 2016

@jemshit I can imagine that occurring if you access the Realm from multiple processes.

By the way, you should consider updating to 1.1.1, it's much more stable than 1.1.0

@Murtowski
Copy link

Murtowski commented Jul 18, 2017

classpath "io.realm:realm-gradle-plugin:3.5.0"

private val listener = RealmChangeListener<T> { t ->
        if (t != null && t.isValid)
            realm.executeTransaction {
                value = realm.copyFromRealm(t)
            }

    }

Listener isn't called after saveCarDetails

fun saveCarDetails(carDetails: CarDetails){
        mRealm.executeTransactionAsync { realm ->
            carDetails.id = 1 // keep only one copy of the object
            realm?.copyToRealmOrUpdate(carDetails)
        }
    }

fun getCarDetails(): LiveData<CarDetails> {
        return (mRealm.where(CarDetails::class.java).equalTo(CarDetails.ID, 1).findFirstAsync()).asLiveData(mRealm)
    }

@cmelchior
Copy link
Contributor

@GitHubMurt Please create a new issue with all details.

@Zhuinden
Copy link
Contributor

Zhuinden commented Jul 18, 2017

@GitHubMurt you did not include asLiveData so we cannot tell what you are doing wrong

@Murtowski
Copy link

I've created new issue as cmelchior suggested
#4984

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Blocked This issue is blocked by another issue T-Bug
Projects
None yet
Development

No branches or pull requests

9 participants