领域和缺少LIMIT:如何执行步骤删除操作?

时间:2016-09-21 10:05:04

标签: android realm

我在Realm for Android中有一些缺少功能的问题。我理解首选模式并不真正需要LIMIT类型的函数,但我有一个非常具体的用例,我没有看到使用当前API的直接解决方案。

我有一个Realm,我在其中保存LogMessage对象。封闭的应用程序可以调用sendLog()方法,该方法将向Realm添加新的LogMessage。

该应用还可以批量将这些LogMessage同步到服务器,并删除已同步的那些。现在问题出在这里:

假设我获得所有LogMessages并希望以100个批次同步它们:

Realm realm = Realm.getInstance(realmConfiguration);
        RealmResults<LogMessage> result = realm.where(LogMessage.class).findAll();
int resultSize = result.size();
int logsPerRequest = 100;

while(result.size() > 0) {
       final List<LogMessage> pageResult = result.subList(0 , Math.min(logsPerRequest, resultSize));
       JsonObject json = new JsonObject();
       JsonElement array = gson.toJsonTree(pageResult, new TypeToken<List<LogMessage>>(){}.getType());
       json.add("events", array);

       RequestBody body = RequestBody.create(JSON, json.toString());
       Request request = new Request.Builder()
                  .url(extras.getString(URL, ""))
                  .post(body)
                  .build();

       //Try to sync
       final Response response = client.newCall(request).execute();
       if (response != null && response.isSuccessful() && response.body() != null) {
             //Delete the synced log messages
             realm.executeTransaction(new Realm.Transaction() {
                      @Override
                      public void execute(Realm realm) {
                                //WHAT NOW?
                      }
             });



      }
}

您可以看到问题所在。我不能只在deleteFromRealm()上调用pageResult,因为它是一个非托管列表。也没有方法可以在领域本身调用deleteFromRealm()并传入要删除的对象列表。

我无法在deleteFromRealm()上拨打result因为这会删除整个列表,而我可能还有LogMessages要同步。

我怎样才能最好地解决这个问题?

1 个答案:

答案 0 :(得分:0)

一种可能性是将整个逻辑移动到单个事务中,从而确保Realm实例和RealmResults在请求时是最新的

    Realm realm = null;
    try {
        realm = Realm.getInstance(realmConfiguration);
        realm.executeTransaction(new Realm.Transaction() {
            public void execute(Realm realm) {
                int logsPerRequest = 100;

                while(realm.where(LogMessage.class).count() > 0) {
                    RealmResults<LogMessage> result = realm.where(LogMessage.class).findAll();
                    final List<LogMessage> pageResult = result.subList(0, Math.min(logsPerRequest, result.size()));
                    JsonObject json = new JsonObject();
                    JsonElement array = gson.toJsonTree(pageResult, new TypeToken<List<LogMessage>>() {}.getType());
                    json.add("events", array);

                    RequestBody body = RequestBody.create(JSON, json.toString());
                    Request request = new Request.Builder().url(extras.getString(URL, "")).post(body).build();

                    //Try to sync
                    final Response response = client.newCall(request).execute();
                    if(response != null && response.isSuccessful() && response.body() != null) {
                        //Delete the synced log messages
                        for(int i = pageResult.size()-1; i >= 0; i--) {
                            LogMessage message = pageResult.get(i);
                            message.deleteFromRealm();
                        }
                    }
                }
            }
        }
    } finally {
        if(realm != null) {
            realm.close();
        }
    }

另一种可能性是(叹息......我不喜欢推荐这种方法)通过内部API(v1.2.0)为代码添加强制刷新。

package io.realm; // <---- this is important 

public class RealmRefresh {
    public static void refreshRealm(Realm realm) {
        Message message = Message.obtain();
        msg.what = HandlerControllerConstants.LOCAL_COMMIT;
        realm.handlerController.handleMessage(msg);
    }
}

你可以做什么

    Realm realm = null;
    try {
        realm = Realm.getInstance(realmConfiguration);
        RealmRefresh.refreshRealm(realm);
        int logsPerRequest = 100;

        while(realm.where(LogMessage.class).count() > 0){
            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    RealmResults<LogMessage> result = realm.where(LogMessage.class).findAll();
                    final List<LogMessage> pageResult = result.subList(0, Math.min(logsPerRequest, result.size()));
                    JsonObject json = new JsonObject();
                    JsonElement array = gson.toJsonTree(pageResult, new TypeToken<List<LogMessage>>() {}.getType());
                    json.add("events", array);

                    RequestBody body = RequestBody.create(JSON, json.toString());
                    Request request = new Request.Builder().url(extras.getString(URL, "")).post(body).build();

                    //Try to sync
                    final Response response = client.newCall(request).execute();
                    if(response != null && response.isSuccessful() && response.body() != null) {
                        //Delete the synced log messages
                        for(int i = pageResult.size() - 1; i >= 0; i--) {
                            LogMessage message = pageResult.get(i);
                            message.deleteFromRealm();
                        }
                    }
                }
            });
            RealmRefresh.refreshRealm(realm);
        }
    } finally {
        if(realm != null) {
            realm.close();
        }
    }

尽管我不喜欢修补内部API,但这对我来说似乎更加强大。