【问题标题】:Realm: The size of filled RealmList in RealmObject is zeroRealm:RealmObject中填充的RealmList的大小为零
【发布时间】:2026-01-14 21:05:02
【问题描述】:

场景:
我有一个模型(DBBasket)可以在本地持久化,添加产品的数量和产品本身。
当用户点击每个产品缩略图下的+按钮时

  • 我在Product中增加totalQuantity
  • 将产品添加到DBBasket
  • 将我从服务器获取的totalProducts 也设置在DBBasket 中。

+按钮中的代码:

holder.HomeProductBindGrid.thatPlusButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            final Product productIns = mProductsList.get(holder.getAdapterPosition());
            mRealm = mRealmManager.getLocalInstance();
            mRealm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(@NonNull Realm realm) {
                    mProductRealm = realm.where(Product.class).equalTo(ProductFields.UNIQUE_ID, productIns.getUniqueId()).findFirst();
....


realm = mRealmManager.getLocalInstance();
realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        String totalNumberOfItemsInBasket = parseDataFromServer(ServerResponse, "numberOfProducts");
        if (totalNumberOfItemsInBasket.matches("")) {
            totalNumberOfItemsInBasket = "0";
        }

        Product product = realm.where(Product.class).equalTo(ProductFields.UNIQUE_ID, prod.getUniqueId()).findFirst();
        if (product == null) {
            product = realm.createObject(Product.class, mProductRealm.getUniqueId());
        }

        if (product != null) {
            if (product.totalQuantity.get() == null) {
                product.totalQuantity.set(0);
                product.totalQuantity.increment(countOrder);
            } else {
                product.totalQuantity.increment(countOrder);
            }
            realm.insertOrUpdate(product);

            DBBasket dbBasket = realm.where(DBBasket.class).findFirst();
            if (dbBasket == null) {
                dbBasket = realm.createObject(DBBasket.class);
            }

            dbBasket.getProducts().add(product);
            dbBasket.setTotalProducts(totalNumberOfItemsInBasket);
            realm.insertOrUpdate(dbBasket);
            Log.wtf("productRealm", dbBasket.getProducts().get(0).getUniqueId() + "");// It shows the UID correctly.
        }
    }
});

由于某种原因,我清理了 Activity Destroy 上的 Product,但没有清理 DBBasket

Realm realm = mRealmManager.getLocalInstance();
    realm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(@NonNull Realm realm) {
            realm.delete(Product.class);
        }
    });

每次用户来到主页面,我都会从服务器接收产品列表,并将它们插入到本地数据库中:

for (int j = 0; j < receivedProductsFromServer.getLength(); j++) {
    final Product product = new Product(...);

    product.setUniqueId(Utils.UniqueIdMaker());

    realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(@NonNull Realm realm) {
          Product productRealm = realm.where(Product.class).equalTo(ProductFields.UNIQUE_ID, product.getUniqueId()).findFirst();
          if (productRealm == null) {
            realm.insert(product);
          }
    }
});

问题:
现在,对于之前添加到DBBasket 的那些产品,我想在那个+ 前面显示他们的totalQuantity
所以我把上面的sn-p代码改成了:

for (int j = 0; j < receivedProductsFromServer.getLength(); j++) {
    final Product product = new Product(...);

    product.setUniqueId(Utils.UniqueIdMaker());

    realm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(@NonNull Realm realm) {
            Product productRealm = realm.where(Product.class).equalTo(ProductFields.UNIQUE_ID, product.getUniqueId()).findFirst();
            if (productRealm == null) {
                DBBasket dbBasketRealm = realm.where(DBBasket.class).findFirst();

                if(dbBasketRealm != null) {
                    RealmList<Product> productInBasket = dbBasketRealm.getProducts(); //Size() is zero!!!

                    RealmResults<Product> productFiltered = productInBasket.where().contains(ProductFields.UNIQUE_ID, product.getUniqueId()).findAll();
                    Product p = productFiltered.get(0);

                    if(p != null) {
                        product.totalQuantity.set(0);
                        product.totalQuantity.increment(Integer.valueOf(p.getQuantity()));
                    } else Log.wtf("productRealm", "productFiltered is Null.");
                }
                realm.insert(product);
            }
        }
    });

但没用!并且dbBasketRealm.getProducts() 的大小为零。


编辑:
+ 调试模式下的按钮:

dbBasketRealm.getProducts() 在调试模式下:


DBBasket 模型:

public class DBBasket extends RealmObject{
    public String totalProducts;
    public RealmList<Product> products;

    public DBBasket() {}
}

产品型号:

public class Product extends RealmObject implements Observable {
    @PrimaryKey
    @Required
    private String uniqueId;
    public final MutableRealmInteger totalQuantity = MutableRealmInteger.valueOf(0);

    public Product() {}
}

【问题讨论】:

  • @TimCastelijns 如果你的意思是DBBasket,我第一次在 + 按钮上填写它。 DBBasket dbBasket = realm.where(DBBasket.class).findFirst(); if (dbBasket == null) {dbBasket = realm.createObject(DBBasket.class);} dbBasket.getProducts().add(product);。并查询onCreate,例如DBBasket dbBasketRealm = realm.where(DBBasket.class).findFirst();
  • 托管对象的 RealmList 不能为空。 O_O
  • @EpicPandaForce 对不起,我的错。我更改了问题的标题并添加了两个Debug模式的屏幕截图。 dbBasketRealm.getProducts() 不为空;它的大小为零!但是怎么办?!我之前用 + 按钮填充并添加到 Realm 中。
  • @EpicPandaForce 当我不清理Product 模型(realm.delete(Product.class))时,DBBasket 上的getProducts 的大小大于零。 DBBasket 不是有自己的产品吗?!当我清理Product 模型时,它也会清理DBBasket?!
  • 如果您从领域中删除产品,则指向它的所有链接也将失效。如果您致电 realm.delete(Product.class),这完全是预期的行为

标签: android realm realm-list


【解决方案1】:

从服务器获取先前添加到购物篮中的产品。然后再次将它们添加到本地数据库。例如OnCreate 中的以下 sn-p 代码:

for (int i = 0; i < receivedFromServer.getLength(); i++) {

realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(@NonNull Realm realm) {
        Product productRealm = realm.where(Product.class).equalTo(ProductFields.UNIQUE_ID, receivedFromServer[i].getUniqueId()).findFirst();

        if (productRealm != null) {
            productRealm.setTotalQuantity(quantity));

            DBBasket dbBasket = realm.where(DBBasket.class).findFirst();
            if (dbBasket == null) {
                dbBasket = realm.createObject(DBBasket.class);
            }

            RealmList<Product> productRealmList = dbBasket.getProducts();
            productRealmList.add(productRealm);
            dbBasket.products = productRealmList;
            dbBasket.setProducts(productRealmList);
            dbBasket.totalProductsSetZero();
            dbBasket.setTotalProducts(quantity));
            realm.insertOrUpdate(dbBasket);
        }
    }
});

【讨论】: