Android:从不正确的线程访问Realm。 Realm对象只能在创建它们的线程上访问

时间:2018-05-28 21:53:54

标签: android android-asynctask realm android-thread

因此,在IntentService内部,应用可能处于活动状态或非活动状态,onHandleIntent会被调用,我将其置于代码下方。这是我将数据存储到域中的位置。

 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();
        }
    }

然后我尝试在onPostExecute的{​​{1}}中访问它,在AsyncTask中,我收到doInBackground,然后将其存储到RealmResults<AppItem>中将其发送到放置此代码的List <AppItem>onPostExecute在这里是ReamObject

appItems

我已经使用 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

2 个答案:

答案 0 :(得分:3)

根据错误消息:在1个线程上获取任何Realm对象后,只能在该线程上访问它们。对其他线程的任何访问都会抛出该异常。

来自AsyncTask的“doInBackground”在后台线程上运行。 “onPostExecute”在UI线程上运行。所以在这里你可以在后台线程上获得Realm对象,并尝试在UI上访问它们的线程=&gt;异常。

您应该在后台线程上执行所有操作,或者在UI线程上执行所有操作。

如果您正在进行非常复杂的查询,我建议在RealmQuery上使用“findAllAsync”,因为这将在后台线程上运行查询,并将它们移动到主线程,但它由Realm在内部处理一种安全的方式。

答案 1 :(得分:1)

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()) {