Just created objects could be touched in any thread, framework does not mind.
new AsyncTask<Void, Void, Dummy>() {
@Override protected Dummy doInBackground(Void... voids) {
Dummy dummy = new Dummy("a", "b");
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
realm.insertOrUpdate(dummy);
realm.commitTransaction();
Debug
.get()
.with(
this,
"THREAD %s %s - %s",
Thread.currentThread().getName(),
dummy.getKey(),
dummy.getValue()
)
.log();
new Thread(new Runnable() {
@Override public void run() {
Debug
.get()
.with(
this,
"THREAD %s %s - %s",
Thread.currentThread().getName(),
dummy.getKey(),
dummy.getValue()
)
.log();
dummy.setValue("c");
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
realm.insertOrUpdate(dummy);
realm.commitTransaction();
Debug
.get()
.with(
this,
"UPDATED : THREAD %s %s - %s",
Thread.currentThread().getName(),
dummy.getKey(),
dummy.getValue()
)
.log();
}
}).start();
return dummy;
}
@Override protected void onPostExecute(Dummy dummy) {
Debug
.get()
.with(
this,
"THREAD %s %s - %s",
Thread.currentThread().getName(),
dummy.getKey(),
dummy.getValue()
)
.log();
}
}.execute();
Output is
THREAD AsyncTask #1 b - a
THREAD main b - a
THREAD Thread-6 b - a
UPDATED : THREAD Thread-6 b - c
Well, let's try to read the database.
new AsyncTask<Void, Void, Dummy>() {
@Override protected Dummy doInBackground(Void... voids) {
Realm realm = Realm.getDefaultInstance();
RealmQuery<Dummy> query = realm.where(Dummy.class);
List<Dummy> list = query.findAll();
Dummy result = null;
for (Dummy dummy : list){
result = dummy;
Debug
.get()
.with(
this,
"THREAD %s %s - %s",
Thread.currentThread().getName(),
dummy.getKey(),
dummy.getValue()
)
.log();
new Thread(new Runnable() {
@Override public void run() {
Debug
.get()
.with(
this,
"THREAD %s %s - %s",
Thread.currentThread().getName(),
dummy.getKey(),
dummy.getValue()
)
.log();
dummy.setValue("c");
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
realm.insertOrUpdate(dummy);
realm.commitTransaction();
Debug
.get()
.with(
this,
"UPDATED : THREAD %s %s - %s",
Thread.currentThread().getName(),
dummy.getKey(),
dummy.getValue()
)
.log();
}
}).start();
if (result != null) break;
}
return result;
}
@Override protected void onPostExecute(Dummy dummy) {
Debug
.get()
.with(
this,
"THREAD %s %s - %s",
Thread.currentThread().getName(),
dummy.getKey(),
dummy.getValue()
)
.log();
}
}.execute();
Output is
THREAD AsyncTask #1 b - c
java.lang.IllegalStateException: Realm access from incorrect thread.
Realm objects can only be accessed on the thread they were created.
OK, lets block onPostExecute.
All the same:
THREAD AsyncTask #1 b - c
java.lang.IllegalStateException: Realm access from incorrect thread.
Realm objects can only be accessed on the thread they were created.
OK, I can see, that you cannot touch RealmObject from different thread.
Docs are right)))
What to do?
Realm offers AutoValue
Let's try.
Installation:
Here is abstract DummyNotARealmObject class:
import com.google.auto.value.AutoValue;
@AutoValuepublic abstract class DummyNotARealmObject{
public static DummyNotARealmObject create(String key, String value) {
return new AutoValue_DummyNotARealmObject(key, value);
}
public abstract String getKey();
public abstract String getValue();
}
... and modified asyncTask:
new AsyncTask<Void, Void, DummyNotARealmObject>() {
@Override protected DummyNotARealmObject doInBackground(Void... voids) {
Realm realm = Realm.getDefaultInstance();
RealmQuery<Dummy> query = realm.where(Dummy.class);
List<Dummy> list = query.findAll();
final DummyNotARealmObject result;
for (Dummy dummy : list){
result = DummyNotARealmObject.create(
dummy.getKey(),
dummy.getValue()
);
Debug
.get()
.with(
this,
"THREAD %s %s - %s",
Thread.currentThread().getName(),
dummy.getKey(),
dummy.getValue()
)
.log();
new Thread(new Runnable() {
@Override public void run() {
Debug
.get()
.with(
this,
"THREAD %s %s - %s",
Thread.currentThread().getName(),
result.getKey(),
result.getValue()
)
.log();
}
}).start();
return result;
}
return null;
}
@Override protected void onPostExecute(DummyNotARealmObject dummy) {
Debug
.get()
.with(
this,
"THREAD %s %s - %s",
Thread.currentThread().getName(),
dummy.getKey(),
dummy.getValue()
)
.log();
}
}.execute();
Output:
THREAD AsyncTask #1 b - c
THREAD main b - c
THREAD Thread-6 b - c
As you can see, now we can easily get access to our Dummy-object's fields from another thread.
All we need is to create abstract class and declare constructor and getters.
This is not as simple as when we use SQLite but I guess Realm is worth it.