Android Realm - Accessing Realm Object from Service

匿名 (未验证) 提交于 2019-12-03 02:29:01

问题:

I have a realm object that is created in my activity. I need to be able to access this object within a service that I created. However I'm getting the error when creating the Realm object within the service

        mRealm = Realm.getInstance(getApplicationContext()); 

java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created

Now I understand this means that because the realm object was created on my activity, I cannot access it from a background thread. However, I'm not finding an easy way around this other than creating my own custom Handler Thread but that just seems like a clunky way of doing it.

Am I missing something here or is there really no better way to be able to access Realm object from within different threads?

Update:

I dug a little deeper to figure out that in an IntentService, the onHandleIntent method runs in a separate thread than other methods within the class. Therefore, I cannot create a class level Realm instance and be able to interact with that inside and outside of the onHandleIntent method. That is what was causing the thread exception. Aside from creating a separate instance of Realm in each method I need to access the object and retrieving it over and over again, I think Ilya Tretyakov's answer will be best. I can copy the object from realm in my constructor and then work with it throughout the life of the service. Any methods that need to write back to the Realm object will need to instantiate their own Realm instance within that method.

回答1:

You can try to use realm.copyFromRealm(youRealmObject);. These method copy Realm data into normal Java objects and detaching them from Realm.

Here is the example of usage:

youRealmObject = realm.copyFromRealm(youRealmObject); 

Here is the information about it from docs:

Makes a standalone in-memory copy of an already persisted RealmObject. This is a deep copy that will copy all referenced objects. The copied object(s) are all detached from Realm so they will no longer be automatically updated. This means that the copied objects might contain data that are no longer consistent with other managed Realm objects. WARNING: Any changes to copied objects can be merged back into Realm using copyToRealmOrUpdate(RealmObject), but all fields will be overridden, not just those that were changed. This includes references to other objects, and can potentially override changes made by other threads.

https://realm.io/docs/java/latest/api/io/realm/Realm.html#copyFromRealm-E-



回答2:

Technically you're supposed to open the Realm instance at the beginning of the background thread, close it at the end of execution in that background that, and pass it to methods in between.

public void handleIntent() { // or doInBackground etc     Realm realm = null;     try {          realm = Realm.getDefaultInstance();          ....           MyObj obj = realm.where(MyObj.class)                           .equalTo(MyObjFields.ID, myObjId)                           .findFirst(); // get by id          ....      } finally {          if(realm != null) {               realm.close(); // important           }      }  }  

Using realm.copyFromRealm() is a workaround, not a solution.


With AS 3.0, you can actually use try-with-resources no matter what your minSDK is (just like if you were using Retrolambda):

public void handleIntent() { // or doInBackground etc     try(Realm realm = Realm.getDefaultInstance()) {          ....           MyObj obj = realm.where(MyObj.class)                           .equalTo(MyObjFields.ID, myObjId)                           .findFirst(); // get by id          ....      } // auto-close }  


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!