Realm Cloudを使ったオフラインファーストなアプリ開発

Realm Cloudを使ったオフラインファーストなアプリ開発

Bf8dccb5b8479c3a589004d3154b6f5f?s=128

Wataru Mizukami

March 18, 2019
Tweet

Transcript

  1. Realm Cloudを使った オフラインファーストなアプリ開発 Wataru Mizukami(水上 亘) Otemachi.apk #02

  2. 自己紹介 Wataru Mizukami/水上 亘         / @tarumzu (たる) Organization/ sikmi,

    inc.
  3. Realmとは - モバイルアプリに組み込んで利用するためのRDBMS - 同じようなシステムとしてSQLiteやCoreDataがある

  4. Realmとは - モバイルアプリに組み込んで利用するためのRDBMS - 同じようなシステムとしてSQLiteやCoreDataがある - 最近、AndroidではRoomなどの登場により、徐々に下火にな りつつある

  5. Realm Cloudとは - Realmの特徴に加え、オフラインファースト機能、リアルタイム データ同期機能がある - オンラインとオフラインでコードを書き分ける必要がない - マルチプラットフォーム間で同期可能

  6. でもこの特徴って、Firebase Realtime DatabaseやCloud Firestoreも大体同じ じゃない?

  7. Firebaseより勝っている点 - RDBなのでクエリで色々イジりたいときに便利 - 電波が不安定なところではローカルDBを優先するため早く処 理できる。Firebaseでは今の所、タイムアウトの機能がないた め待ちが発生する オフラインファーストという点で考えればまだ需要はある!

  8. それでは実践!

  9. 実践: アカウント登録 まずは下記からアカウント登録 https://cloud.realm.io/login

  10. 実践: インスタンス作成 作成したらWebコンソールのCreate New Instanceボタンからインスタンス を作成 選べるリージョンは下記2つ - US West

    - Germany
  11. 実践: インスタンス設定 アプリからRealm Cloudへログインす る方式を選択 - おすすめはJWT方式 - 注) 別途JWTを発行するサーバーを自

    前で用意するのが面倒。 - デフォルトでNicknameやAnonymous方 式が有効になっているので無効にする のを忘れずに
  12. 実践: スキーマ定義 open class Test1( @PrimaryKey var testId: Int =

    0, var testList: RealmList<Test2>? = null ): RealmObject()
  13. 実践: スキーマ定義 open class Test1( @PrimaryKey var testId: Int =

    0, var testList: RealmList<Test2>? = null ): RealmObject() - Openでスキーマクラスを定義 - RealmObjectを継承する
  14. 実践: スキーマ定義 open class Test1( @PrimaryKey var testId: Int =

    0, var testList: RealmList<Test2>? = null ): RealmObject() - 主キーにはPrimaryKeyアノ テーションを付与 - 必ず一つ主キーを保つ必要 がある - 複合キーは出来ないので注 意
  15. 実践: スキーマ定義 open class Test1( @PrimaryKey var testId: Int =

    0, var testList: RealmList<Test2>? = null ): RealmObject() リレーションはRealmListで定義
  16. 実践: アプリからRealm Cloudへのログイン val credentials = SyncCredentials.jwt(“authToken”) SyncUser.logInAsync(credentials, "https://${getString(R.string.realm_instance_address)}/auth", object

    : SyncUser.Callback<SyncUser> { override fun onSuccess(result: SyncUser) { // ログイン成功した場合の処理 } override fun onError(error: ObjectServerError) {} })
  17. 実践: アプリからRealm Cloudへのログイン val credentials = SyncCredentials.jwt(“authToken”) SyncUser.logInAsync(credentials, "https://${getString(R.string.realm_instance_address)}/auth", object

    : SyncUser.Callback<SyncUser> { override fun onSuccess(result: SyncUser) { // ログイン成功した場合の処理 } override fun onError(error: ObjectServerError) {} }) この例ではJWT認証を利用
  18. 実践: アプリからRealm Cloudへのログイン val credentials = SyncCredentials.jwt(“authToken”) SyncUser.logInAsync(credentials, "https://${getString(R.string.realm_instance_address)}/auth", object

    : SyncUser.Callback<SyncUser> { override fun onSuccess(result: SyncUser) { // ログイン成功した場合の処理 } override fun onError(error: ObjectServerError) {} }) 非同期でログイン処理を行う
  19. 実践: マイグレーション val config = SyncConfiguration.Builder(SyncUser.current(), "realms://${getString(R.string.realm_instance_address)}/${uid}/myRealm").waitForInit ialRemoteData().schemaVersion(1).build() Realm.setDefaultConfiguration(config)

  20. 実践: マイグレーション val config = SyncConfiguration.Builder(SyncUser.current(), "realms://${getString(R.string.realm_instance_address)}/${uid}/myRealm").waitForInit ialRemoteData().schemaVersion(1).build() Realm.setDefaultConfiguration(config) -

    ネットに繋がっている場合は データの同期が終わるまで待 つ。繋がっていなければス キップ
  21. 実践: マイグレーション val config = SyncConfiguration.Builder(SyncUser.current(), "realms://${getString(R.string.realm_instance_address)}/${uid}/myRealm").waitForInit ialRemoteData().schemaVersion(1).build() Realm.setDefaultConfiguration(config) テーブル構成のバージョンを定

    義。構成を変更する場合はバー ジョンを上げることでマイグレー ションしてくれる
  22. 実践: マイグレーション val config = SyncConfiguration.Builder(SyncUser.current(), "realms://${getString(R.string.realm_instance_address)}/${uid}/myRealm").waitForInit ialRemoteData().schemaVersion(1).build() Realm.setDefaultConfiguration(config) DefaultConfigに設定することで、

    以後Realm.XXXでDBにアクセス できる
  23. あとは通常のRealmの使い方と同じ

  24. 実践: おまけ Realm.getInstanceAsync(requireNotNull(Realm.getDefaultConfiguration()), object : Realm.Callback() { override fun onSuccess(result:

    Realm) { result.executeTransactionAsync { realm -> var test1 = realm.where(Test1::class.java).equalTo("testId",1.toInt()).findFirst() test1 ?: run { realm.insertOrUpdate(Test1()) } } } })
  25. 実践: おまけ Realm.getInstanceAsync(requireNotNull(Realm.getDefaultConfiguration()), object : Realm.Callback() { override fun onSuccess(result:

    Realm) { result.executeTransactionAsync { realm -> var test1 = realm.where(Test1::class.java).equalTo("testId",1.toInt()).findFirst() test1 ?: run { realm.insertOrUpdate(Test1()) } } } }) - 非同期でインスタンスを取得
  26. 実践: おまけ Realm.getInstanceAsync(requireNotNull(Realm.getDefaultConfiguration()), object : Realm.Callback() { override fun onSuccess(result:

    Realm) { result.executeTransactionAsync { realm -> var test1 = realm.where(Test1::class.java).equalTo("testId",1.toInt()).findFirst() test1 ?: run { realm.insertOrUpdate(Test1()) } } } }) - このブロック内では最後自動 的にコミットされる
  27. 実践: おまけ Realm.getInstanceAsync(requireNotNull(Realm.getDefaultConfiguration()), object : Realm.Callback() { override fun onSuccess(result:

    Realm) { result.executeTransactionAsync { realm -> var test1 = realm.where(Test1::class.java).equalTo("testId",1.toInt()).findFirst() test1 ?: run { realm.insertOrUpdate(Test1()) } } } }) - testId1のデータを取得
  28. 実践: おまけ Realm.getInstanceAsync(requireNotNull(Realm.getDefaultConfiguration()), object : Realm.Callback() { override fun onSuccess(result:

    Realm) { result.executeTransactionAsync { realm -> var test1 = realm.where(Test1::class.java).equalTo("testId",1.toInt()).findFirst() test1 ?: run { realm.insertOrUpdate(Test1()) } } } }) - testId1がなかったら作成して Insert
  29. まとめ - 簡単にクラウドに接続できる - RDBの強力なクエリが使える - オフラインファースト限定であればまだ戦える

  30. 宣伝 4/14開催の技術書典6でSwift/Kotlin愛好会合同執筆本として、 日本で唯一!のRealm Cloud入門書書くのでぜひ買いに来てくだ さい!他にも内容盛りだくさんです。 場所は「け18」 よろしくおねがいします! https://techbookfest.org/event/tbf06/circle/71750003

  31. ご清聴、ありがとうございました!