Skip to content

The best DataStore utils to ensure type safety. (最好用的 DataStore 工具,可以确保类型安全)

Notifications You must be signed in to change notification settings

DylanCaiCoding/DataStoreKTX

Repository files navigation

DataStoreKTX

English | 中文

License

Jetpack DataStore is a data storage solution that uses Kotlin Coroutines or RxJava to store data in an asynchronous manner with consistent transaction methods. Its usage is different from other storage solutions such as SharedPreferences and MMKV, making it more special. Therefore, there are not many good DataStore encapsulations available online. I have done a lot of exploration and attempts and finally developed a very satisfactory set of usage methods, which I hope can help everyone.

Features

  • No need to create DataStore, RxDataStore, or Preferences.Key objects;
  • Supports both Kotlin Coroutines and RxJava usage;
  • Uses property names as key names, eliminating the need to declare a large number of key name constants;
  • Ensures type safety and avoids exceptions caused by inconsistent types or key name.

DataStore vs MMKV

Which one to choose between DataStore and MMKV? It is recommended to read this article. If you find the article too long, you can directly read the summary. As for the view of DataStore, it needs to be modified a little bit, because DataStore now supports not only Kotlin Coroutines, but also RxJava usage. Therefore, DataStore is also suitable for Java projects.

If you plan to use MMKV, you can use my other library MMKV-KTX. If you choose to use DataStore, then this library is your best choice.

Basic Usage

Add the following to the root build.gradle file:

allprojects {
    repositories {
        //...
        maven { url 'https://www.jitpack.io' }
    }
}

Add the following dependencies to the module's build.gradle file:

dependencies {
    implementation 'com.github.DylanCaiCoding.DataStoreKTX:datastore-ktx:1.0.0'
    // Optional
    implementation 'com.github.DylanCaiCoding.DataStoreKTX:datastore-rxjava2:1.0.0'
    implementation 'com.github.DylanCaiCoding.DataStoreKTX:datastore-rxjava3:1.0.0'
}

Inherit the DataStoreOwner class in a class, and then use the by xxxxPreference() function to delegate the property to DataStore. For example:

object SettingsRepository : DataStoreOwner(name = "settings") {
  val counter by intPreference()
  val language by stringPreference(default = "zh")
}

If you already have a superclass that cannot be inherited, implement IDataStoreOwner by DataStoreOwner(name) instead, for example:

object SettingsRepository : BaseRepository(), IDataStoreOwner by DataStoreOwner(name = "settings") {
  //...
}

Make sure that the name used is not duplicated so that type safety can be 100% guaranteed!!!

The following delegation functions that use the property name as the retrieval key value are supported:

  • intPreference()
  • longPreference()
  • booleanPreference()
  • floatPreference()
  • doublePreference()
  • stringPreference()
  • stringSetPreference()

The get() function that calls this property reads the data by executing dataStore.data.map {...}, for example:

// Call in coroutine
val language = SettingsRepository.language.get()
// val language = SettingsRepository.language.getOrDefault()

The set() function that calls this property saves the data by executing dataStore.edit {...}, for example:

// Call in coroutine
SettingsRepository.counter.set(100)
SettingsRepository.counter.set { (this ?: 0) + 1 }

This property can also be used as Flow or LiveData. In this way, a notification callback is made each time the data changes, which can be used to update UI or to write streaming code. For example:

SettingsRepository.counter.asLiveData()
  .observe(this) {
    tvCount.text = (it ?: 0).toString()
  }
SettingsRepository.counter.asFlow()
  .map { ... }

Adaptation to RxJava

By default, only Coroutine is supported. You can perform some simple adaptations to extend it to support RxJava. First, add the dependency datastore-rxjava2 or datastore-rxjava3 to build.gradle.

dependencies {
    // Optional
    implementation 'com.github.DylanCaiCoding.DataStoreKTX:datastore-rxjava2:1.0.0'
    implementation 'com.github.DylanCaiCoding.DataStoreKTX:datastore-rxjava3:1.0.0'
}

Then change the DataStoreOwner class to the RxDataStoreOwner class, and it will be adapted. It's recommended to add the @JvmStatic annotation to the property, which will make Java code calling this property more concise.

object SettingsRepository : RxDataStoreOwner(name = "settings") {
  @JvmStatic
  val counter by intPreference()
}

The new getAsync() function call of this property reads the data by executing rxDataStore.updateDataAsync(prefsIn -> ...), and the return value is Single<T>, for example:

SettingsRepository.getCounter().getAsync()
    .subscribe(counter -> {
      //...
    });

The new setAsync() function call of this property writes the data by executing rxDataStore.data().map(prefs -> ...), for example:

SettingsRepository.getCounter().setAsync(100);
SettingsRepository.getCounter().setAsync((counter, prefsIn) -> counter + 1);

It can also be used as a Flowable. In this way, a notification callback is made each time the data changes, which can be used to update UI or to write streaming code. For example:

SettingsRepository.getCounter().asFlowable()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(counter -> tvCounter.setText(String.valueOf(counter)));

Coroutine and RxJava usage can be used together, as long as it is the same property, and the read/write functions operate on the same data source.

Update Log

Releases

Other Libraries by the Author

Library Introduction
Longan Possibly the easiest-to-use Kotlin utility library
LoadingStateView Decoupling the title bar or view of loading, loading failure, no data, etc., supporting two-line code integration into the base class
ViewBindingKTX The most comprehensive ViewBinding tool
MMKV-KTX The most flexible and easy-to-use MMKV tool
Tracker A lightweight tracking framework based on Buzzvideo's view tree tracking idea

License

Copyright (C) 2023. Dylan Cai

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

About

The best DataStore utils to ensure type safety. (最好用的 DataStore 工具,可以确保类型安全)

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published