Reputation: 3450
I'm trying to use realm as a persistence method of the downloaded data from an API. I'm getting the error: *
Caused by: java.lang.IllegalStateException: This Realm instance has already been closed, making it unusable.
and I don't know what I'm doing wrong with the persistence methods. My class for persistence is the next:
public class PersistenceManager {
@Inject
public PersistenceManager(){}
public void saveHabitants(final List<Habitant> habitants){
Realm realm = Realm.getDefaultInstance(); // opens db
try {
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.insertOrUpdate(habitants);
}
});
} finally {
realm.close();
}
}
public void saveHabitant(final Habitant habitant){
Realm realm = Realm.getDefaultInstance();
try {
realm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
realm.insertOrUpdate(habitant);
}
});
} finally {
realm.close();
}
}
public List<Habitant> loadHabitants(){
Realm realm = Realm.getDefaultInstance();
List<Habitant> results;
try {
results = realm.where(Habitant.class).findAll();
} finally {
realm.close();
}
return results;
}
public List<Habitant> loadHabitants(int indexFrom, int limit){
Realm realm = Realm.getDefaultInstance();
List<Habitant> results;
try {
results = realm.where(Habitant.class).findAll();
results.subList(indexFrom, limit);
} finally {
realm.close();
}
return results;
}
public Habitant loadHabitant(long id){
Realm realm = Realm.getDefaultInstance();
Habitant result;
try {
result = realm.where(Habitant.class).equalTo("id", id).findFirst();
} finally {
realm.close();
}
return result;
}
}
When I used the method loadHabitants(int indexFrom, int limit)
is when I get this error.
Upvotes: 0
Views: 944
Reputation: 81529
A RealmResults is accessible through lazy loading (per accessor) for as long as there is at least 1 open Realm instance on the given thread.
I actually intended to refer to the documentation, but for some reason I couldn't find it? Anyways, a RealmResults is accessed lazily, so when there are no open Realm instances, it becomes invalid, and can no longer be accessed. This is true for RealmObjects as well.
The docs do say:
...RealmObjects and RealmResults are accessed through a lazy cache...
so you cannot return a managed RealmResults, and expect it to remain open, if you close the thread-local Realm instance it is associated with.
Two solutions:
1.) refer to the documentation on how to properly manage Realm lifecycle on UI thread and background thread
2.) use realm.copyFromRealm()
, which eagerly evaluates the whole data set, creates a detached copy of it. Please note that this is not a free operation, larger data sets can easily cause UI thread to freeze up if you use copyFromRealm()
on UI thread.
public List<Habitant> loadHabitants(int indexFrom, int limit){
try(Realm realm = Realm.getDefaultInstance()) {
List<Habitant> results = realm.where(Habitant.class).findAll();
results = new ArrayList<>(results.subList(indexFrom, limit));
for(int i = 0, size = results.size(); i < size; i++) {
results.set(i, realm.copyFromRealm(results.get(i)));
}
return Collections.unmodifiableList(results);
}
}
Upvotes: 1