realm / realm-java

Realm is a mobile database: a replacement for SQLite & ORMs
http://realm.io
Apache License 2.0
11.45k stars 1.75k forks source link

Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created. #7339

Closed kunalgharate closed 2 years ago

kunalgharate commented 3 years ago

Hello team ,

working on the realm for the project but I have multiple fragments where I have inserting data and updating same the data. I am using the realm data source class which I got in OFishWild - An open source project developed by MongoDB Team but when I updating the data its throwing the error accessing on an incorrect thread.

Step of update :

  1. Query for getting the current object

fun getResidentDetails(id: String): ResidentUser? { if (id.isBlank()) return null return realm.where().equalTo("_id", ObjectId(id)).findFirst() }

2. Update the object as per required changes 
3. Pass data to ViewModel 
4. Pass data to real singleton Class

fun updateResident(_residentUser: ResidentUser , id: String) {

 var residentUser =  realm.where<ResidentUser>().equalTo("_id", ObjectId(id)).findFirst()
    realm.executeTransactionAsync({
        residentUser = _residentUser
        realm.insertOrUpdate(residentUser)
    }, {
        Log.d(TAG, "updateResident: Updated item")
    }, {
        Log.d(TAG, "updateResident: ${it.localizedMessage}")
    })
}

https://github.com/WildAid/o-fish-android/blob/main/app/src/main/java/org/wildaid/ofish/data/RealmDataSource.kt

kunalgharate commented 3 years ago

Please send me any projects where I can get the idea of how to pass data using MVVM to the realm

@realm-support I don't see any large projects on Github for complex data like filter data, sorting data, search data with any design pattern

@realmanalytics @RealmBot @realm

cmelchior commented 3 years ago

Hi @https://github.com/realm/realm-java/tree/master/examples/coroutinesExample could be one such example.

In your code sample, you just need to move the query inside the write transaction like this:

    realm.executeTransactionAsync({
        var residentUser =  realm.where<ResidentUser>().equalTo("_id", ObjectId(id)).findFirst()

        // You don't need this, just modify residentUser directly
        realm.insertOrUpdate(residentUser)
    }, {
        Log.d(TAG, "updateResident: Updated item")
    }, {
        Log.d(TAG, "updateResident: ${it.localizedMessage}")
    })
}

The reason you are getting the exception is that executeTransactionAsync() runs on a separate thread, so using Realm data outside that thread will throw. I would recommend this article for a deeper explanation: https://academy.realm.io/posts/threading-deep-dive/