I wrote an object in realm in getResourceData method and deleting it in onKeyExited method. But I am not able to as it is giving error in onKeyExited method. Adding object runs perfectly.
Stack trace points error at below line:
<<< if (ResourcesOnlineResults2.size() > 0) { >>>
private void getResourceData(final String key, final String id) {
final Realm mRealm = Realm.getDefaultInstance();
mOnlineResourceDatabaseRef = FirebaseDatabase.getInstance().getReference().child(Constants.FIREBASE_CHILD_ONLINE_RESOURCE).child(mJobType).child(key);
mOnlineResourceDatabaseRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
mMapResourceList.put(id, dataSnapshot.getValue(ResourceOnline.class));
final ResourceOnline resourceOnline = dataSnapshot.getValue(ResourceOnline.class);
mRealm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.copyToRealmOrUpdate(resourceOnline);
}
});
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
mRealm.close();
}
@Override
public void onKeyExited(String key) {
Realm realm = Realm.getDefaultInstance();
// Remove any old marker
Marker marker = this.mMapMarkers.get(key);
if (marker != null) {
final ResourceOnline resourceOnline = mMapResourceList.get(marker.getId());
final RealmResults<ResourceOnline> ResourcesOnlineResults2 = realm.where(ResourceOnline.class).equalTo("resourceId",resourceOnline.getResourceId()).findAllAsync();
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
if (ResourcesOnlineResults2.size() > 0) {
ResourcesOnlineResults2.deleteAllFromRealm();
}else{
Log.v("wai", "onKeyExited Realmsize is zero ");
}
}
});
marker.remove();
this.mMapMarkers.remove(key);
mMapResourceList.remove(marker.getId());
}
realm.close();
}
java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
at io.realm.BaseRealm.checkIfValid(BaseRealm.java:383)
at io.realm.RealmResults.isLoaded(RealmResults.java:913)
at io.realm.RealmResults.size(RealmResults.java:413)
at com.waiapp.Booking.MapViewFragment$4.execute(MapViewFragment.java:420)
at io.realm.Realm$2.run(Realm.java:1351)
at io.realm.internal.async.BgPriorityRunnable.run(BgPriorityRunnable.java:34)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
at java.lang.Thread.run(Thread.java:818)
Realm version(s): 2.2.0
Realm sync feature enabled: no
Android Studio version: 2.2.0
Which Android version and device: 6.0.1 and moto g2
You need to load the data inside the transaction:
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
final ResourceOnline resourceOnline = mMapResourceList.get(marker.getId());
final RealmResults<ResourceOnline> ResourcesOnlineResults2 = realm.where(ResourceOnline.class).equalTo("resourceId",resourceOnline.getResourceId()).findAllAsync();
if (ResourcesOnlineResults2.size() > 0) {
ResourcesOnlineResults2.deleteAllFromRealm();
}else{
Log.v("wai", "onKeyExited Realmsize is zero ");
}
}
});
Otherwise they are loaded on the wrong thread
@cmelchior the findAllAsync() should be findAll() for background thread synchronous query to delete result set
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
final RealmResults<ResourceOnline> ResourcesOnlineResults2 = realm.where(ResourceOnline.class)
.equalTo("resourceId",resourceOnline.getResourceId())
.findAll();
if (ResourcesOnlineResults2.size() > 0) {
ResourcesOnlineResults2.deleteAllFromRealm();
}else{
Log.v("wai", "onKeyExited Realmsize is zero ");
}
}
});
}
I kinda hope that resourceOnline isn't a managed RealmObject, because then it would be
final String resourceId = resourceOnline.getResourceId();
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
final RealmResults<ResourceOnline> ResourcesOnlineResults2 = realm.where(ResourceOnline.class)
.equalTo("resourceId", resourceId)
@cmelchior Thanks problem is resolved but I didnt understand why I need to load data inside Transaction method.
@Zhuinden Yes resourceOnline is a managed RealmObject. Can you please tell me more when to do Async or synchronous queries.
Is there any active slack group for realm I can join.
@kevivforever there is a slack, but it didn't look active when I was there.
But in that case, this is the right way:
final String resourceId = resourceOnline.getResourceId();
realm.executeTransactionAsync(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
final RealmResults<ResourceOnline> ResourcesOnlineResults2 = realm.where(ResourceOnline.class)
.equalTo("resourceId", resourceId)
.findAll();
//...
You need to query the data inside the transaction, because async() means that transaction block will run on another thread. So trying to access data from the original thread will break the Realm threading model, which doesn't allow reading Realm data across multiple threads.
Closing
Thanks for all the help. Sorry for not closing it on time.
Most helpful comment
You need to load the data inside the transaction:
Otherwise they are loaded on the wrong thread