【问题标题】:Your Realm is opened from a thread without a Looper您的领域是从没有 Looper 的线程打开的
【发布时间】:2016-11-05 05:54:50
【问题描述】:

我以为我正在遵循推荐的 Realm 方法来运行这样的异步数据插入:

public void addCustomer(final Customer customer) {
        Realm insertRealm = Realm.getDefaultInstance();
        insertRealm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm backgroundRealm) {
                long id = customerPrimaryKey.incrementAndGet();
                customer.setId(id);
                backgroundRealm.copyToRealm(customer);
            }
        }, new Realm.Transaction.OnSuccess() {
            @Override
            public void onSuccess() {
                Log.d(LOG_TAG, "Customer Added");
            }
        }, new Realm.Transaction.OnError() {
            @Override
            public void onError(Throwable error) {
                Log.d(LOG_TAG, error.getMessage());
            }
        });

        insertRealm.close();

    }

但是,当我运行上面的代码时,我得到“你的领域是从一个没有 Looper 的线程打开的,并且你提供了一个回调,我们需要一个处理程序来调用你的回调”

我在非 Activity 类中运行此代码,我在这里做错了什么以及如何修复它。谢谢。

更新 - 已修复 事实证明查询没有问题,问题是我是从 IntentService 调用它的。我试图在应用程序首次运行时为数据库播种,所以我修复了这个问题:

protected void onHandleIntent(Intent intent) {
        Realm realm = Realm.getDefaultInstance();

        //Add sample Customers to database
        List<Customer> customers = SampleCustomerData.getCustomers();

        realm.beginTransaction();
        for (Customer customer: customers){
            customer.setId(customerPrimaryKey.getAndIncrement());
            realm.copyToRealm(customer);
        }
        realm.commitTransaction();

realm.close();

    }

已修复,在 IntentService 之外,从 UI 线程调用查询时可以正常工作。

【问题讨论】:

  • 这是从 Presenter 类中调用的。我没有启动线程,我认为 Realm 会自旋一个线程来执行异步查询。

标签: android realm


【解决方案1】:

为了

insertRealm.executeTransactionAsync(new Realm.Transaction() {
      @Override
        public void execute(Realm backgroundRealm) {
            //...
        }
    }, new Realm.Transaction.OnSuccess() {
        @Override
        public void onSuccess() {
            // !!!
        }
    }, new Realm.Transaction.OnError() {
        @Override
        public void onError(Throwable error) {
            // !!!
        }
    });

要在后台线程上调用的异步事务回调,该线程需要与 Looper 关联(因此具有可以与该 Looper 的线程通信的 Handler)。


解决办法,在后台线程上使用同步事务。

但你已经明白了。

protected void onHandleIntent(Intent intent) {
    Realm realm = null;
    try {
        realm = Realm.getDefaultInstance();
        final List<Customer> customers = SampleCustomerData.getCustomers();
        realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm realm) {
                for (Customer customer: customers){
                    customer.setId(customerPrimaryKey.getAndIncrement());
                    realm.insert(customer);
                }
            }
        });
    } finally {
        if(realm != null) {
            realm.close();
        }
    }
}

【讨论】:

    【解决方案2】:

    Realm 依赖于 Hanfler 和 Looper 类的 Android 线程通信。 看起来您从另一个后台线程查询异步操作(为什么?,它已经在后台,使用同步版本)。 要解决这个问题,您需要使用 Active Looper 的线程。使用 Handler 线程作为后台线程 - 它将初始化 Looper

    【讨论】:

    • 您介意提供一个示例吗,我正在运行由 Presenter 调用的存储库中的代码。我可以访问此类中的 Context 对象,我该如何解决这个问题。
    【解决方案3】:

    您需要从 UI 线程调用 addCustomer

    【讨论】:

    • 嗯,其实它是从IntentService的onHandleIntent调用的,让我看看是不是这个问题。
    【解决方案4】:

    试试这条线

    insertRealm.close();
    

    onSuccessonError 方法中添加。照原样从最后一行删除它。

    所以你的代码看起来像

    public void addCustomer(final Customer customer) {
            final Realm insertRealm = Realm.getDefaultInstance();
            insertRealm.executeTransactionAsync(new Realm.Transaction() {
                @Override
                public void execute(Realm backgroundRealm) {
                    long id = customerPrimaryKey.incrementAndGet();
                    customer.setId(id);
                    backgroundRealm.copyToRealm(customer);
                }
            }, new Realm.Transaction.OnSuccess() {
                @Override
                public void onSuccess() {
                    Log.d(LOG_TAG, "Customer Added");
                    insertRealm.close();
                }
            }, new Realm.Transaction.OnError() {
                @Override
                public void onError(Throwable error) {
                    Log.d(LOG_TAG, error.getMessage());
                    insertRealm.close();
                }
            });
        }
    

    【讨论】:

      猜你喜欢
      • 2016-05-07
      • 1970-01-01
      • 2016-06-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多