安卓:从错误的线程访问Realm。Realm对象只能在创建它们的线程上访问。

4

IntentService内部,应用程序可能处于活动或非活动状态,在调用onHandleIntent时,我放置了下面的代码。这是我将数据存储到realm中的地方。

 Realm realm = null;
    try { 
        realm = Realm.getDefaultInstance();
        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {

                for (AppItem item : items) {
                    AppItem item2 = realm.createObject(AppItem.class, UUID.randomUUID().toString());
                    item2.mName = item.mName;
                    item2.mCount = item.mCount;
                    item2.mUsageTime = item.mUsageTime;
                }
            }
        });
    } finally {
        if (realm != null) {
            realm.close();
        }
    }

然后我试图在AsyncTask中的onPostExecute中访问它,在doInBackground中,我获取RealmResults<AppItem>,然后将其存储到List <AppItem> 中并将其发送到放置此代码的onPostExecute。 这里的appItems是ReamObject。

 Realm backgroundRealm = Realm.getDefaultInstance();
            backgroundRealm.executeTransactionAsync(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    for (AppItem item : appItems) { 
 //getting error here   if (item.mUsageTime <= 0) continue;
                        mTotal += item.mUsageTime;
                        item.mCanOpen = mPackageManager.getLaunchIntentForPackage(item.mPackageName) != null;


               }
              }
            });

我已经使用executeTransactionAsync进行了两次操作,但仍然出现以下错误。

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

7
根据错误信息:一旦您在一个线程上获取任何Realm对象,它们只能在该线程上访问。在其他线程上的任何访问都会抛出该异常。
AsyncTask中的“doInBackground”在后台线程上运行。“onPostExecute”在UI线程上运行。因此,在后台线程上获取Realm对象,并尝试在UI线程上访问它们=> 异常。
您应该在后台线程上执行所有操作,或者在UI线程上执行所有操作。
如果您正在执行非常复杂的查询,则建议在RealmQuery上使用“findAllAsync”,因为这将在后台线程上运行查询,并将它们移动到主线程上,但是由Realm在内部以安全的方式处理。

2
for (AppItem item : appItems) { 
如果appItems包含您在UI线程上从RealmResults获取的托管RealmObjects,则在后台线程中访问它们将失败。 realm.executeTransactionAsync((realm) -> {会给您一个运行在Realm线程执行器上的Realm作为参数,因此必须在事务内使用对象来获取托管的RealmResults/RealmObjects。
因此,如果对象是托管的,则需要在realm.executeTransactionAsync内重新查询对象。
            public void execute(Realm realm) {
                for (AppItem item : realm.where(AppItem.class).findAll()) { 

1
谢谢,我已经阅读了你关于Realm的博客!它们真的很棒。 - MrRobot9

0

我发现了同样的错误,因为它在不同的线程中。

我用以下方法解决了这个问题:

// Repository Class
scope.launch(Dispatchers.Main) {
     // Your Code
}

// View Model
viewModelScope.launch(Dispatchers.Main) {
    // Your Code
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接