Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Android领域-从服务访问领域对象_Java_Android_Multithreading_Realm - Fatal编程技术网

Java Android领域-从服务访问领域对象

Java Android领域-从服务访问领域对象,java,android,multithreading,realm,Java,Android,Multithreading,Realm,我有一个在活动中创建的领域对象。我需要能够在我创建的服务中访问此对象。但是,我在服务中创建领域对象时遇到了错误 mRealm = Realm.getInstance(getApplicationContext()); java.lang.IllegalStateException:来自错误线程的域访问。 领域对象只能在创建它们的线程上访问 现在我明白了这意味着因为领域对象是在我的活动上创建的,所以我不能从后台线程访问它。然而,除了创建自己的自定义处理程序线程之外,我并没有找到一

我有一个在活动中创建的领域对象。我需要能够在我创建的服务中访问此对象。但是,我在服务中创建领域对象时遇到了错误

        mRealm = Realm.getInstance(getApplicationContext());
java.lang.IllegalStateException:来自错误线程的域访问。 领域对象只能在创建它们的线程上访问

现在我明白了这意味着因为领域对象是在我的活动上创建的,所以我不能从后台线程访问它。然而,除了创建自己的自定义处理程序线程之外,我并没有找到一种简单的方法来解决这个问题,但这似乎是一种笨拙的方法

我是否在这里遗漏了什么,或者是否真的没有更好的方法可以从不同的线程中访问领域对象

更新:


我深入研究了一下,发现在IntentService中,onHandleIntent方法比类中的其他方法运行在单独的线程中。因此,我无法创建类级领域实例,也无法在onHandleIntent方法内外与之交互。这就是导致线程异常的原因。除了在每个方法中创建一个单独的Realm实例来访问对象并一次又一次地检索它之外,我认为Ilya Tretyakov的答案将是最好的。我可以在构造函数中从领域复制对象,然后在服务的整个生命周期中使用它。任何需要写回Realm对象的方法都需要在该方法中实例化它们自己的Realm实例。

您可以尝试使用
Realm.copyFromRealm(youRealmObject)。这些方法将领域数据复制到普通Java对象中,并将它们与领域分离

以下是用法示例:

youRealmObject = realm.copyFromRealm(youRealmObject);
以下是文档中关于它的信息:

创建已持久化RealmObject的独立内存中副本。 这是一个深度副本,将复制所有引用的对象。复制品 对象都已从领域中分离,因此它们将不再 自动更新。这意味着复制的对象可能会 包含不再与其他托管域一致的数据 物体。警告:对复制对象的任何更改都可以合并回 使用copyToRealmOrUpdate(RealmObject)进入领域,但所有字段都将 被覆盖,而不仅仅是那些被改变的。这包括 对其他对象的引用,并且可能会覆盖所做的更改 通过其他线程


从技术上讲,您应该在后台线程开始时打开领域实例,在后台执行结束时关闭它,并将其传递给中间的方法

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 
         } 
    } 
} 
使用
realm.copyFromRealm()
是一种变通方法,而不是解决方案


使用AS 3.0,无论您的minSDK是什么,您都可以实际使用
try With resources
(就像您使用Retrolambda一样):


当他们将一个实例限制为一个线程时,这是一件很尴尬的事情。您可以向活动发布runnable,它将在活动线程上运行(如果您仍然可以访问该活动)。建议的方法是在服务中执行查询,以获取相同的对象并在服务中使用该对象。如果对象有主键,事情就会简单。您可以执行
MyObject obj=mRealm.where(MyObject.class).equalTo(“id”,123).findFirst()
。当您在服务中更改
obj
时,活动中的对象将在下一个UI循环中自动更改。您可以使用intent在它们之间传递主键。请参阅并感谢您提及
尝试使用资源
提示。我不知道AS 3上的此功能
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
}