realmio - realm对象只能从创建它们的线程中访问

时间:2016-08-29 07:27:00

标签: android thread-safety realm

问题声音类似于之前提出的问题。我已经提到了那些但无法找到我遇到的这个问题的解决方案。

private AddCartItemDialog.CartItemListener cartItemListener = new AddCartItemDialog.CartItemListener() {
        @Override
        public void onOkClick(Product cartItem, int quantity) {

            realm.executeTransactionAsync(new Realm.Transaction() {
                @Override
                public void execute(Realm bgRealm) {

                    DraftInvoice draftInvoice = bgRealm.where(DraftInvoice.class).equalTo("shop.id", shopId).findFirst();


                    InvoiceItem invoiceItem = bgRealm.createObject(InvoiceItem.class);
                    invoiceItem.setPrice(cartItem.getPrice());
                    invoiceItem.setId(cartItem.getId());
                    invoiceItem.setQuantity(quantity);
                    invoiceItem.calculateTotal();

                    draftInvoice.getInvoiceItems().add(invoiceItem);

                    updateCartItemCount(draftInvoice.getInvoiceItems().size());
                }
            }, () -> {

            }, error -> {
                error.printStackTrace();
                Logger.e(error.getMessage());
            });

        }

        @Override
        public void onCancelClick() {

        }
    };

错误日志显示以下错误 -

08-28 15:10:25.214 4996-4996/com.example.realshoptest W/System.err: java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
08-28 15:10:25.214 4996-4996/com.example.realshoptest W/System.err:     at io.realm.BaseRealm.checkIfValid(BaseRealm.java:449)
08-28 15:10:25.214 4996-4996/com.example.realshoptest W/System.err:     at io.realm.ProductRealmProxy.realmGet$price(ProductRealmProxy.java:159)
08-28 15:10:25.214 4996-4996/com.example.realshoptest W/System.err:     at com.example.realshoptest.models.Product.getPrice(Product.java:75)
08-28 15:10:25.214 4996-4996/com.example.realshoptest W/System.err:     at com.example.realshoptest.NewInvoiceActivity$1$1.execute(NewInvoiceActivity.java:76)
08-28 15:10:25.214 4996-4996/com.example.realshoptest W/System.err:     at io.realm.Realm$1.run(Realm.java:1187)
08-28 15:10:25.214 4996-4996/com.example.realshoptest W/System.err:     at io.realm.internal.async.BgPriorityRunnable.run(BgPriorityRunnable.java:34)
08-28 15:10:25.214 4996-4996/com.example.realshoptest W/System.err:     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:422)
08-28 15:10:25.214 4996-4996/com.example.realshoptest W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
08-28 15:10:25.214 4996-4996/com.example.realshoptest W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
08-28 15:10:25.214 4996-4996/com.example.realshoptest W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
08-28 15:10:25.214 4996-4996/com.example.realshoptest W/System.err:     at java.lang.Thread.run(Thread.java:818)
08-28 15:10:25.214 4996-4996/com.example.realshoptest E/TestShopApp: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.

此行发生错误 - invoiceItem.setPrice(cartItem.getPrice());

这段代码似乎与我的理解有关,但并不是因为我在同一个线程中异步访问对象。我在这里缺少什么?

1 个答案:

答案 0 :(得分:1)

public void onOkClick(Product cartItem, int quantity) {

此行从UI线程的Realm Instance

接收Product
        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm bgRealm) {

此调用为后台线程

创建一个Realm实例
                invoiceItem.setPrice(cartItem.getPrice());

cartItem仍然属于UI线程的Realm实例,因此无法在后台线程上访问

两种解决方案:

1。)仅将参数发送到后台线程

    public void onOkClick(Product cartItem, int quantity) {
        final long cartItemId = cartItem.getId();
        final String price = cartItem.getPrice();
        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm bgRealm) {
                DraftInvoice draftInvoice = bgRealm.where(DraftInvoice.class).equalTo("shop.id", shopId).findFirst();
                InvoiceItem invoiceItem = bgRealm.createObject(InvoiceItem.class);
                invoiceItem.setPrice(price);
                invoiceItem.setId(cartItemId);

2.)使用后台线程的Realm实例重新查询对象

    public void onOkClick(Product cartItem, int quantity) {
        final long cartItemId = cartItem.getId();
        realm.executeTransactionAsync(new Realm.Transaction() {
            @Override
            public void execute(Realm bgRealm) {
                Product product = bgRealm.where(Product.class).equalTo("id", cartItemId).findFirst();
                DraftInvoice draftInvoice = bgRealm.where(DraftInvoice.class).equalTo("shop.id", shopId).findFirst();
                InvoiceItem invoiceItem = bgRealm.createObject(InvoiceItem.class);
                invoiceItem.setPrice(product.getPrice());
                invoiceItem.setId(cartItemId);

第二种解决方案更清洁。