realm-gradle-plugin 2.2.1 と Android Realm Browser
- はじめに
- なにが駄目だったのか
- realm-gradle-plugin 2.2.1 に変更後に、更に修正した箇所
- 古いコードのバージョンアップ(12/9追記)
- で使いたかった Android Realm Browser の対応
- Realm自体は範囲外の小話的なメモ
はじめに
この記事は
Android その3 Advent Calendar 2016 - Qiita
の四日目の記事です。
- 昨日は numa08 - Qiita さんの なぜ我々はData Bindingを利用するのか、テストの観点から考えてみる - Qiita のお話です
- 明日は matsuokah - Qiita さんのAndroidのコードを書く前にコーディングに集中できる状態を作る - will and wayのお話です
昨日までの話は
- Android 2.3 Canary 2 で試す realm-android - exception think
- やっぱり駄目だったよ realm-gradle-plugin 2.2.1(=>解決しました) - exception think
annotationProcessor 対応の realm-gradle-plugin 2.2.1
でうまく動かせなかったことをblogに書いた所、Realm のSlack で zakiさんに言及して頂き
解決までサポートしていただきました。大変ありがとうございます。
試した環境は
- Android Studio 2.3 Canary 2
- android gradle plugin 2.3.+
- data-binding も併用
なにが駄目だったのか
Android 6系の端末で run-as が効かないため Android Realm Browserを導入していた所、
そちらの依存していたRealmが古すぎるため誤動作が起きてビルドができなかった
の記事に乗っていたやつですね。。
変更前
compile 'com.github.dmytrodanylyk.realm-browser:library:0.0.3'
=>
変更後
compile ('com.github.dmytrodanylyk.realm-browser:library:0.0.3'){ exclude module: 'io.realm' }
コレでビルド自体は通るようになり、soの duplicateエラー も解決
確かに
realm-browser/build.gradle at master · dmytrodanylyk/realm-browser · GitHub
の指定を見ると
compile 'io.realm:realm-android:0.83.1'
でビルドされています・・*1
gradleの指定で勘違いしていた所
aarで提供されているライブラリの場合、googleのライブラリとかだと
compile 'com.android.support:appcompat-v7:23.1.0'
とか依存が無視されて本体側のが利用されるので
realmとかもそうだと思ってましたorz。
強参照なんですね。。(汗
realm-gradle-plugin 2.2.1 に変更後に、更に修正した箇所
Realm.instanceの取得方法
- Realm.getDefaultInstance()
- Realm.setDefaultConfiguration()
が使えるようになったので、そこら辺は記述を戻しました
- 一旦戻したコード*2
public class RealmUtils{ public static Realm getInstance(){ return Realm.getDefaultInstance(); } //Applicationクラス等で初期化する public static void setConfiguration(Context context) { Realm.setDefaultConfiguration(buildRealmConfiguration(context)); } private static RealmConfiguration buildRealmConfiguration(Context context) { return new RealmConfiguration.Builder(context)//★ .deleteRealmIfMigrationNeeded() .schemaVersion(1L) .name("testApp") //filename .build(); } }
- => 変更後(2.2.1 ver)
public class RealmUtils{ public static Realm getInstance(){ return Realm.getDefaultInstance(); } public void setConfiguration(Context context) { Realm.setDefaultConfiguration(buildRealmConfiguration(context)); } private RealmConfiguration buildRealmConfiguration(Context context) { Realm.init(context); //★ return new RealmConfiguration.Builder()//★ .deleteRealmIfMigrationNeeded() .schemaVersion(1L) .name("testApp") //filename .build(); } }
データ操作関数(例:削除)
- 変更前(前回 ver)
RealmResults<User> result = realm.where(User.class).findAll();
result.clear()
でしたが、実際動かしてみた所、動作もしませんでした。*3
- 変更後(2.2.1 ver)
RealmResults<User> result = realm.where(User.class).findAll();
result.deleteAllFromRealm()
にしたら動くようになりました。
allObjectsSortedがなくなっていた
results = realm.allObjectsSorted(User.class, "createAt", true);
=>
results = realm.where(User.class) .findAllSorted("createAt", Sort.ASCENDING);
ようはRealm変数に生えていたデータ操作関数が廃止されたってことなんでしょうね・・
- 参考
古いコードのバージョンアップ(12/9追記)
@PrimaryKey に設定されている変数がObject型だとエラーになる*4
新しいRealmObjectの変数は、全部NULL許可
- @PrimaryKey付いていたObject変数にもその属性がついてしまう
- @PrimaryKeyはNotNullが必須なので、スキーマエラーになりgetInstanceがエラーor NULL になる
Realm.init(context); return new RealmConfiguration.Builder() .schemaVersion(REALM_SCHEMA_VERSION) //★要インクリメント .migration(new MyMigration()) .build();
public class MyMigration implements RealmMigration { /** Current Schema Version. */ public static final long REALM_SCHEMA_VERSION = 1; @Override public void migrate(DynamicRealm realm, long oldVersion, long newVersion) { Log.d(getClass().getSimpleName(), "Migrate Realm Schema old[" + oldVersion + "] to new[" + newVersion + "]"); if (oldVersion == 0) { // Migrate from v0 to v1 migrate0To1(realm); oldVersion++; } if (oldVersion < newVersion) { throw new IllegalStateException(String.format("Migration missing from v%d to v%d", oldVersion, newVersion)); } } /** * Migrate from version 0 to version 1. * At version 1, add @Required annotation for Primary Key(historyForShow) at SearchHistory Table. * * @param realm */ private void migrate0To1(DynamicRealm realm) { RealmObjectSchema userSchema = realm.getSchema().get(User.class.getSimpleName()); userSchema.isRequired("key"); } }
で使いたかった Android Realm Browser の対応
- realm-gradle-plugin 2.2.1 に差し替えたままでは動きませんでした
compile 'io.realm:realm-android:0.83.1'
のころの記述のせいか、最新のversionでは動きません
で fork 修正されたもので一番最新に対応されているものを探してみます
だと
realm-browser/build.gradle at master · atsushi-ageet/realm-browser · GitHub
classpath "io.realm:realm-gradle-plugin:1.0.0"
とバージョンは低いですが、realm-pluginを使っていますので、動かせそうです
で導入してみます
- app/build.gradle
compile ('com.github.atsushi-ageet:realm-browser:0.0.6'){ exclude group: 'io.realm' }
- app/XXXActivity
Realm realm = Realm.getDefaultInstance(); com.dd.realmbrowser.RealmBrowser.getInstance().addRealmConf(realm.getConfiguration()); com.dd.realmbrowser.RealmBrowser.startRealmFilesActivity(activity);
呼び出し方も以前と変わっているようですね。
でもまあ、
startRealmFilesActivity(Activity)
=>
startRealmFilesActivity(Context)
とかだと使い勝手が上がるのにな。。とか思ったりも*5
Realm自体は範囲外の小話的なメモ
新しいバージョンで
という書き方は理解したのですが
@RealmClass public class UserSimple implements RealmModel { @PrimaryKey public long id; public String name; public String email; public int age; }
public class UserHoge extends UserSimple
と書くと、RealmObjectと同じく継承エラーが出るのは変わらず。。
結局
- Realm用のDtoを別途作る
- UserSimpleはそのまま。Gson変換に頼る
みたいなお話になってしまったり。。
でも、対象クラスが implements Parcelable だとGsonがtoJson等でうまく変換できないんですよね・・*8
どっちもG様のプロダクトのはずなんですが何でなんでしょう。。
辺りしかググっても引っかからないけど、使い方が今一わからないorz