酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Realm Javaのv0.80.3からv0.90.0にアップデートしたらビルドが通らなくなった

久しぶりにRealm Javaを使ったアプリをアップデートすることになり色々と手を入れている最中なのですが、使用しているライブラリのひとつの「Realm Java」も古いバージョンのものを使っていたのでこの機会にアップデートさせようとしました。

この記事ではv0.80.3からv0.90.0へのアップデートで起こった問題について記載します。

ベースのコードはv0.80.3以前のものなので v0.80.3 時点で非推奨になっていたコードもあるかもしれません。…と先に書いておきます。

Realm Java 0.90.0へアップデートする

まずRealm Javaの追加の方法から変更になっていました。アップデートに際してapp/build.gradleの数字部分を変更するだけではダメでした。

dependencies {
  // ...
  compile 'io.realm:realm-android:0.80.3'
  // ...
}

app/build.gradleのdependenciesから削除して、ファイルの先頭あたりに追加する。

apply plugin: 'com.android.application'
apply plugin: 'realm-android'

build.gradleのbuildscript.dependenciesにclasspathを追加する。

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.0.0'
        classpath 'io.realm:realm-gradle-plugin:0.90.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

これでRaelm Javaの新しいバージョンをインストールすることができるようになりました。

ビルドエラーの対策

次に、アップデート方法の変更でわかるようにv0.80.3からv0.90.0へは少し時間があいていたようで、従来のコードでRealmビルドエラーが発生するようになってしまっていたようです。

allObjectsSortedがなくなっていた

allObjectsSorted(Class,String,bool)自体が消えていてビルドが通らなくなっていました。

昔から存在していたのか調べていませんが、allObjectsSorted(Class,String,Sort)が追加されていたようです。しかし、切り替える以前に非推奨になったいたようです。

results = realm.allObjectsSorted(Favorite.class, 
                                 "createAt", true);

results = realm.where(Favorite.class)
               .findAllSorted("createAt", Sort.ASCENDING);

RealmChangeListener.onChange()が引数付きに変更されていた

Realmのデータベースが変更されるとアプリ側で通知を受け取るができる仕組みがあります。RealmChangeListener.onChange()に引数が追加されていました。

@Override
public void onChange() {
    adapter.notifyDataSetChanged();
}

@Override
public void onChange(Object element) {
    adapter.notifyDataSetChanged();
}

データベースにデータが追加されていない

上記のビルドエラーを修正してアプリの起動自体はできるようになりました。

開発中のアプリではJSONファイルを読み込んでRealmのデータベースへデータを追加します。しかし一部のデータがデータベースに追加されていません。

Realm.createAllFromJsonメソッドでJSONを読み込んだ時に失敗しているようで、ログを見たところ例外が発生しているようでした。

java.lang.IllegalArgumentException: Trying to set non-nullable field price to null.

W/System.err: java.lang.IllegalArgumentException: Trying to set non-nullable field price to null.
W/System.err:     at io.realm.UserRealmProxy.createOrUpdateUsingJsonObject(UserRealmProxy.java:451)

Realm Java v0.83で導入されたこの変更の影響しているのかもしれません。

これを踏まえて修正しました。

public class User extends RealmObject {
    @PrimaryKey
    private int code;
    private int price;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public int getPrice() {
        return price;
    }

    public void setPrice(int price) {
        this.price = price;
    }
}

public class User extends RealmObject {
    @PrimaryKey
    private int code;
    private Integer price;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public Integer getPrice() {
        return price;
    }

    public void setPrice(Integer price) {
        this.price = price;
    }
}

関係ありそうな部分をブログ用にピックアップしてきただけなので実際のコードとは異なるのですが、Userクラスにpriceフィールドがいてる……