Jetpack DataStore with Kotlinx Serialization


こんにちは!今回のリリースでは、kotlixのシーケンス化によりデータストレージに情報を格納および書き込む方法についてのプレゼンテーションを作成します.
従来のDataStoreを使用する方法は、Preferences DataStoreとProto DataStoreの2つです.
この方法はProto DataStore法と類似しており,ボイラプレートコードをきれいにする利点がある.
まず、kotlixのシーケンス化を使用する依存項目を設定します.
project/build.gradle
dependencies {
        classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
}


module/build.gradle
plugins {
	id "kotlin"
	id "org.jetbrains.kotlin.plugin.serialization"
}

dependencies {
	implementation "org.jetbrains.kotlinx:kotlinx-serialization-json-jvm:1.3.2"
}
まず、プロジェクトの最上位レベルとモジュールレベルの指向性コピーを設定します.
次に、Serilizationを使用する情報に適用します.
import kotlinx.serialization.Serializable

@Serializable
data class UserPreferences(
	val firstName: String,
    val lastName: String,
    val address: String
)
Serializerの設定:
object UserPreferencesSerializer : Serializer<UserPreferences> {

	override val defaultValue: UserPreferences = UserPreferences()

	override suspend fun readFrom(input: InputStream): UserPreferences {
		try {
			return Json.decodeFromString(
				UserPreferences.serializer(), input.readBytes().decodeToString()
			)
		} catch (e: SerializationException) {
			throw CorruptionException("Unable to read UserPrefs", e)
		}
	}

	override suspend fun writeTo(t: UserPreferences, output: OutputStream) {
		output.write(
			Json.encodeToString(UserPreferences.serializer(), t).encodeToByteArray()
		)
	}
}
オプション(Optional)Hiltを使用するユーザーは、モジュールを作成してDataStoreに注入できます.
@Module
@InstallIn(SingletonComponent::class)
object DataStoreModule {

	@Provides
    @Singleton
    fun provideUserPrefsDataStore(
        @ApplicationContext context: Context
    ) : DataStore<UserPreferences> {
        return DataStoreFactory.create(
            serializer = UserPreferencesSerializer,
            produceFile = { context.dataStoreFile("user_prefs.json")
        )
    }
}

@Module
@InstallIn(SingletonComponent::class)
interface RepositoryModule {
	
    @Provides
    @Singleton
    fun bindUserPrefsRepository(userRepository: UserRepositoryImpl): UserRepository
}
私はDataStoreをRepositoryモードで使用しますが、ビューモデルや他の場所で使用する人は必要ありません.
(Optional) Repository, UseCases
class UserPrefsRepositoryImpl @Inject constructor(
	private val dataStore: DataStore<UserPreferences>
) : UserPrefsRepository {

	override fun getUserPrefs(): Flow<UserPreferences> = dataStore.data
    
    override suspend fun setFirstName(firstName: String) {
    	dataStore.updateData { it.copy(firstName = firstName) }
    }
    
    override suspend fun setLastName(lastName: String) {
    	dataStore.updateData { it.copy(lastName = lastName) }
    }
    
    override suspend fun setAddress(address: String) {
    	dataStore.updateData { it.copy(address = address) }
    }
}

class GetUserPrefsUseCase @Inject constructor(
	private val userPrefsRepository: UserPrefsRepository
) {
	
    operator fun invoke() = userPrefsRepository.getUserPrefs()
}
ビューモデルからデータを取得しましょう.
@HiltViewModel
class ViewModel(
	private val getUserPrefsUseCase: GetUserPrefsUseCase
) : ViewModel() {

	val userInfo = getUserPrefesUseCase().stateIn(
    	viewModelScope, SharingStarted.WhileSubsribed(5000), null
    )
}