DEV Community

kaede
kaede

Posted on • Edited on

Android 基礎 -- Part 05 Datastore に保存するための Repository の save メソッドを作成する

why

ステートに持った値を保存したい。
DB にはまだ繋がず、とりあえず Datastore に保存する。

Gauge のアプリでレスポンスを シナリオデータストアに入れていたように
Android でもデータストアに入れる。

https://www.youtube.com/watch?v=aQyphCXeVHg&list=PLgAI_5b_7BdRaBPAD5RMrzjoSwefDXpkw&index=7

SharedPreference という名前で使えるらしい。


Datastore Preferences 1.0 をインポート

dependencies {
//...
    implementation 'androidx.datastore:datastore-preferences:1.0.0'
}
Enter fullscreen mode Exit fullscreen mode

App の build.gradle の dependecies の implementation で
androidx の datastore の datastore-preferences:1.0.0
これを書き、 sync してインストールする


Repository (Driver) を作成して Datastore に書き込めるようにする

https://www.youtube.com/watch?v=uvAbY38CNXU&list=PLgAI_5b_7BdRaBPAD5RMrzjoSwefDXpkw&index=8

コンポーザブルからは呼び出すだけで、処理担当を分ける。
実際にデータを書き込む処理は、Repository に書く。
クリーンアーキテクチャで言う、Driver 相応だろう。

現状、アプリのディレクトリ構造として

  • screen / edit / EditNoteScreen.kt
  • ui / theme /
  • MainActivity.kt
  • NoteApp.kt

この構造になっている。

ここに package として repository / を追加する。
その中にインターフェースとして NoteRepository を作る。

Drive というより、インターフェースだから Port っぽいな


インターフェースである reposotiry / NoteRepository で save と load を定義する

実装する前のインターフェースとして、クリーアーキテクチャで言う
Port のようなものを作る。実装と呼び出し先を繋げるものだ。

ここでは save と load を作る。

package com.example.hellojetpack.repository

interface NoteRepository {
    suspend fun save(body: String)
    suspend fun load(): String
}
Enter fullscreen mode Exit fullscreen mode

インターフェースを TODO で実装する repository / datastore / DatastoreNoteRepository で save と load を実装する。

とりあえず TODO で実装する。

実際の実装クラスを書く。
クリーンアーキテクチャでいう Driver のパッケージに書くものだ。

MokeLab さんのやり方では Repository パッケージの中に
さらに datastore パッケージを作って、中に書くらしい。

なので、先ほど作った repository / のなかに datastore / を作って、その中に DatastoreNoteRepositrory.kt を作った。

class DatastoreNoteRepository: NoteRepository {
    override suspend fun save(body: String) {
        TODO("Not yet implemented")
    }

    override suspend fun load(): String {
        TODO("Not yet implemented")
    }
}
Enter fullscreen mode Exit fullscreen mode

中身は、NoteRepository のインターフェースを
implement members してガワを作った。


DatastoreNoteRepository のために Context に noteStore というプロパティを用意する。

https://www.youtube.com/watch?v=uvAbY38CNXU&list=PLgAI_5b_7BdRaBPAD5RMrzjoSwefDXpkw&index=8

この Android X のデータストアを使うためには Android の Context を使って、その中にプロパティを用意する必要があるらしい。

Context とは、React における Redex のような、どのコンポーザブルからでも読み書きのできる置き場所だと解釈する。

https://developer.android.com/topic/libraries/architecture/datastore?hl=ja#preferences-create

Kotlin ファイルの最上位、つまり一番最初にインスタンスが一度作られるらしい。そしてシングルトンで保持できるらしい。

https://e-words.jp/w/%E3%82%B7%E3%83%B3%E3%82%B0%E3%83%AB%E3%83%88%E3%83%B3.html

シングルトンとは、一つしかインスタンスが作られないことで、つまり共通データにアクセスされるコンテキストのことだと解釈する。

import android.content.Context
import androidx.datastore.preferences.core.Preferences

val Context.noteStore: DataStore<Preferences> by preferencesDataStore(
    "note"
)
Enter fullscreen mode Exit fullscreen mode

Android Context のなかに noteStore と言うプロパティを作成
型は先ほど依存に追加した Android X DataStore の Preferences とする。
これで Gauge で言う Scenario Datastore のように
Android の Preference Datastore として
キーバリューストアが使えるようになると解釈した。


PreferencesDatastore のための Preference Key を用意する

https://youtu.be/uvAbY38CNXU?t=200

val BODY_KEY = stringPreferenceKey("body")
Enter fullscreen mode Exit fullscreen mode

データストアは キーバリュー ストアなので
次はキーを作る。
Preference Datastore を作ったので、対応する
Preferecne Key を作った。


Context.noteStore に Repository の save メソッドで引数のキーと中身の値が入るようにする。

val Context.noteStore: DataStore<Preferences> by preferencesDataStore(
    "note"
)

class DatastoreNoteRepository: NoteRepository {
    override suspend fun save(body: String) {
        TODO("Not yet implemented")
    }

    override suspend fun load(): String {
        TODO("Not yet implemented")
    }
}
Enter fullscreen mode Exit fullscreen mode

現状、Preference の Datastore を使って
Context に noteStore プロパティを生やしている。

save メソッドの中身には何もない。

class DatastoreNoteRepository(
    private val context: Context
): NoteRepository {
    override suspend fun save(body: String) {
        TODO("Not yet implemented")
    }
}
Enter fullscreen mode Exit fullscreen mode

コンストラクタ インジェクションで
クラス生成時に一度だけ context インスタンスができるようにする。

    override suspend fun save(body: String) {
        context.noteStore.edit { pref ->
            pref[BODY_KEY]  = body
        }
    }
Enter fullscreen mode Exit fullscreen mode

引数の body を
ストアの BODY_KEY と言うキーのバリューとして入れる。

Top comments (0)