在Android的领域移动平台中计算自定义冲突解决方案

时间:2016-12-27 21:24:47

标签: android realm realm-mobile-platform

我想为此方案设置自定义分辨率: 1-在离线模式下,在一个设备中的realmobject中增加一个整数字段 2-在离线模式下,在另一个设备的同一个realmobject中增加相同的整数字段 默认的自定义分辨率是最后更新获胜但在我的情况下我想要 两个设备的增量在上次更新后对结果生效。 我试过这段代码进行测试:

Realm realm = Realm.getDefaultInstance();
            final RealmResults<Number> results= realm.where(Number.class).findAll();

            realm.executeTransaction(new Realm.Transaction() {
                @Override
                public void execute(Realm realm) {
                    int num = results.get(0).getNumber()+1;
                    results.get(0).setNumber(num);
                }
            });

Number类是这样的:

public class Number extends RealmObject {
@PrimaryKey
private String id;
private int number;

public String getId() {
    return id;
}
public void increment(){
    this.number++;
}
public void setId(String id) {
    this.id = id;
}

public int getNumber() {
    return number;
}

public void setNumber(int number) {
    this.number = number;
}

这个问题对我的应用非常重要。如果我不能在客户端这样做 我将无法使用我感兴趣的领域移动平台。

3 个答案:

答案 0 :(得分:0)

也许你可以使用这些对象的命令列表,将它们保持在离线状态并在上线时同步/合并。命令可以是incrementdecrementmultiplyBy2等等。

文档说:

    Inserts in lists are ordered by time. 
    If two items are inserted at the same position, the item that was
    inserted first will end up before the other item. This means that
    if both sides append items to the end of a list they will end up in
    order of insertion time.

因此,您将始终拥有按日期排序的已应用命令列表。

答案 1 :(得分:0)

文档目前说协议支持计数器但尚未在语言级别公开,所以我猜你必须自己实现它。

最简单的方法是将其存储为List整数(1用于递增,-1用于递减),然后使用List.sum()({{ 3}})快速获得汇总结果。

public class Counter extends RealmObject {
    private int count;

    public int    getCount() { return count; }
    public void   setCount(int count) { this.count = count; }
}

public class Number extends RealmObject {
    @PrimaryKey
    private String id;
    private RealmList<Counter> counters;

    public void incrementNumber(){
        Counter c = realm.createObject(Counter.class);
        c.setCount(1);
        this.getCounters().add(c);
    }

    public int getNumber() {
        // Get the aggregate result of all inc/decr
        return this.getCounters().sum("count");
    }

    public void setNumber(int number) {
        this.getCounters().deleteAllFromRealm();

        Counter c = realm.createObject(Counter.class);
        c.setCount(number);
        this.getCounters().add(c);
    }

    public String getId() { return id; }
    public void setId(String id) { this.id = id; }
    private RealmList<Counter> getCounters() { return counters; }
    private void setCounters(RealmList<Counter> counters) { this.counters = counters; }
}

```

答案 2 :(得分:0)

感谢@ast代码示例。我也通过缓存命令模式解决了这个问题,这里是我的代码:

public class CommandPattern extends RealmObject {
@PrimaryKey
private String id;
private String commandName;

public String getCommandName() {
    return commandName;
}

public void setCommandName(String commandName) {
    this.commandName = commandName;
}

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}}
 @Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_increment:
            if (isOnline()) {
                realm = Realm.getDefaultInstance();
                realm.executeTransaction(new Realm.Transaction() {
                    @Override
                    public void execute(Realm realm) {
                        updateNumberOnRealm();
                    }
                });
                realm.close();
            } else {
                addMethodToCache("increment");
            }
public void addMethodToCache(final String methodName) {
    realm = Realm.getDefaultInstance();
    realm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            commandPattern = new CommandPattern();
            commandPattern.setId(UUID.randomUUID().toString());
            commandPattern.setCommandName(methodName);
            realm.copyToRealmOrUpdate(commandPattern);
        }
    });
    realm.close();
}

public void invokeCachedCommands() {
    realm = Realm.getDefaultInstance();
    commandsCached = realm.where(CommandPattern.class).findAll();
    commandsCached.addChangeListener(new RealmChangeListener<RealmResults<CommandPattern>>() {
        @Override
        public void onChange(final RealmResults<CommandPattern> element) {
            if(!element.isEmpty()) {
                realm.executeTransaction(new Realm.Transaction() {
                    @Override
                    public void execute(Realm realm) {
                        for (CommandPattern command : element) {
                            if(command != null) {
                                if (command.getCommandName().equals("increment")) {
                                    //updateNumberOnRealm();
                                    RealmResults<Number> results = realm.where(Number.class).findAll();
                                    results.get(0).increment();
                                    command.deleteFromRealm();
                                }
                            }
                        }
                    }

                });
            }
        }

    });


    realm.close();

}

在完成增量操作之前,我检查在线状态,如果它处于脱机状态,则会在Command Pattern对象中缓存增量字符串 再次上线后,通过以下代码调用这些缓存的命令:

IntentFilter intentFilter = new IntentFilter(NetworkStateChangeReceiver.NETWORK_AVAILABLE_ACTION);
    LocalBroadcastManager.getInstance(this).registerReceiver(new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            boolean isNetworkAvailable = intent.getBooleanExtra(IS_NETWORK_AVAILABLE, false);
            if (isNetworkAvailable) {
                invokeCachedCommands();
            }else{
                if(commandsCached != null) {
                    commandsCached.removeChangeListeners();
                }
            }

        }
    }, intentFilter);

这是一般的自定义冲突解决方案,可用于任何类型的命令