Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update only NOT NULL values when writing data to Realm

Tags:

android

realm

Helo everyone! My scenario is that i have a screen with a feed and every feed item with it's detail is stored in a realm. Each of these items has offset and feedPostedAt properties defined. The problem comes when a user clicks on a item and item's detail is downloaded to provide current data. However the downloaded detail doesn't contain properties offset and feedPostedAt therefore when i update in the realm (realm.copyOrUpdate()) this item the old item with defined offset and feedPostedAt properties will be overwritten.

Is there a way that realm updates only values that are defined and leaves properties with NULL values untouched?

Right now i'm dealing with this problem in a way that i manually reset offset and feedPostedAt property but it's not nice nor effective.

like image 821
Jan Staněk Avatar asked Sep 08 '15 10:09

Jan Staněk


1 Answers

It could be a bit of late but this is what I use. The method updates base object with non-default valued properties of update object. Then Realm#insertOrUpdate method is used to update realm database.

    /**
 * Both classes must be detached from realm.
 * Primitives compared with their defaults.
 * check <a href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.5"/>default values of primitives</>
 */
public static <T> void updateObject(T base, T update) {
    Class<?> aClass = base.getClass();
    for (Field field : aClass.getDeclaredFields()) {
        try {
            field.setAccessible(true);
            Class<?> fieldType = field.getType();
            if (fieldType.isPrimitive()) {
                if (fieldType.equals(boolean.class)) {
                    if (field.getBoolean(update)) {
                        field.setBoolean(base, true);
                    }
                } else if (fieldType.equals(int.class)) {
                    if (field.getInt(update) != 0) {
                        field.setInt(base, field.getInt(update));
                    }
                } else if (fieldType.equals(long.class)) {
                    if (field.getLong(update) != 0L) {
                        field.setLong(base, field.getLong(update));
                    }
                } else if (fieldType.equals(short.class)) {
                    if (field.getShort(update) != (short) 0) {
                        field.setShort(base, field.getShort(update));
                    }
                } else if (fieldType.equals(byte.class)) {
                    if (field.getByte(update) != (byte) 0) {
                        field.setByte(base, field.getByte(update));
                    }
                } else if (fieldType.equals(float.class)) {
                    if (field.getFloat(update) != 0.0f) {
                        field.setFloat(base, field.getFloat(update));
                    }
                } else if (fieldType.equals(double.class)) {
                    if (field.getDouble(update) != 0.0d) {
                        field.setDouble(base, field.getDouble(update));
                    }
                } else if (fieldType.equals(char.class)) {
                    if (field.getChar(update) != '\u0000') {
                        field.setChar(base, field.getChar(update));
                    }
                }
            } else {
                Object newValue = field.get(update);
                if (newValue != null) {
                    field.set(base, newValue);
                }
            }
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
  • It uses reflection to access all properties.
  • Both objects must be detached from realm.
  • The object model should have @PrimaryKey annotated property in order Realm#insertOrUpdate to do its job. Otherwise method requires a bit of tuning.
like image 50
guness Avatar answered Nov 15 '22 06:11

guness