在Android中链接领域查询的最佳做法是什么?

时间:2017-08-11 01:23:38

标签: android realm

所以,我有一个使用realm.io的Android应用程序。我必须像这样异步运行查询:

public static void getProductsByCategoryId(Realm realm, 
     String categoryId,
     OrderedRealmCollectionChangeListener<RealmResults<Product>> callback) {

    RealmResults<Product> result = realm.where(Product.class)
            .equalTo(CATEGORY, categoryId)
            .findAllAsync();
    result.addChangeListener(callback);
}

回调将处理此响应,但随后我需要按顺序运行另一个查询。那么,你将有queryA =&gt;过程响应=&gt; queryB =&gt;过程响应。所以,回调可能有这样的代码

.....
getProductsByCategoryId(app.getRealmInstance(), "ABC123", firstCallback);
.....
private OrderedRealmCollectionChangeListener<RealmResults<Product>> firstCallback = new OrderedRealmCollectionChangeListener<RealmResults<Product>>() {

        @Override
        public void onChange(RealmResults<Product> realmProducts, OrderedCollectionChangeSet changeSet) {

                mProdList.addAll(mRealm.copyFromRealm(realmProducts));

                // get more product info (2nd call)
                MainApplication.getMoreProductInfo(mRealm, mCatId, false, secondCallback);
        }
    };

目前,我的理解是你会在queryA的回调中运行queryB吗?查看应用程序的要求,我最终会得到3个或4个查询链。这是一种合适的方法,还是我应该使用的特定模式?我还没有在Realm文档中找到任何指导。

2 个答案:

答案 0 :(得分:1)

如果您需要执行多个查询以检索结果集,这通常表示架构设计错误,因为Realm的工作方式是,如果您可以使用一个查询定义查询结果(并且你不使用你通常不需要使用的realm.copyFromRealm()),然后它的元素和结果本身都是延迟加载的。

如果你无法做到这一点,那么即使这样,通常你也不应该链接find*Async个电话,因为你没有存储为字段变量的任何 RealmResults都有机会由GC消耗,当isLoaded()为真时,不会调用其更改侦听器(因为所述RealmResults不再存在)。

所以你真正想做的只是在后台线程上执行多个查询然后将复制的结果返回给主线程,在这种情况下它看起来就像这样

Executor executor = Executors.newSingleThreadedPool(); // or some other pool
Handler handler = new Handler(Looper.getMainLooper());

public void getQueryResults(DataLoadedCallback callback) {
    executor.execute(() -> {
        try(Realm realm = Realm.getDefaultInstance()) {
            realm.refresh(); // <-- might not be necessary
            RealmResults<XYZ> results1 = realm.where(XYZ.class)./*...*/.findAll();
            RealmResults<ZXY> results2 = realm.where(ZXY.class)./*...*/.findAll();
            RealmResults<YZX> results3 = realm.where(YZX.class)./*...*/.findAll();
            List<Something> someList = new LinkedList<>(); 
            for/*do magic transform things*/
                someList.add(blah /* blah is not a managed RealmObject */);
            }
            handler.post(() -> {
                callback.onDataLoaded(Collections.unmodifiableList(new ArrayList<>(someList)));
            });
        }
    });
}

答案 1 :(得分:0)

在回调中链接查询很好,“应该可以正常工作”,但如果你能表达你想要的尽可能少的查询,效率会更高。

理想情况下,我们应该使用足够强大的查询语言在一个查询中表达您想要的所有内容。我们尚未完全到达那里,但我们非常有兴趣了解您的具体要求。

此外,不清楚为什么在您发布的方法中使用copyFromRealm,但是在理想情况下这不是必需的。