歓迎の設定データストア🚀


こんにちは、開発者、この記事では、Jetpackライブラリの新しいメンバーをカバーするつもりです🚀 データストアと呼ばれます.
我々は、いくつかのデータをローカルのAndroidアプリでローカルに格納するために長い間共有の設定に取り組んでいると我々はどのように共有設定は非常に我々のユースケースをサポートするために有用であることが分かった.
私たちの生活を容易にするためにAndroidは、より効率的な方法で我々のアプリで共有設定を実装するためにDatastoreを導入しています.
Datastoreは2種類の実装を提供します設定DatastoreとProto Datastore.今日、我々は好みのデータストアを見ています.

So, why should we use Preferences DataStore? 😕

  • It is an Async API that can be used via Flow
  • It is safe to call on UI thread since work is moved to Dispatchers.IO under the hood
  • It can signal errors
  • It is safe from runtime exceptions
  • It has a transactional API with strong consistency
  • It handles data migration from Shared Preferences

この男は、いくつかの利点があります!😃
さて、コードに直接ジャンプしましょう💻

For this example I have used Dagger-Hilt to provide dependency Injection.


我々のビルドを更新しましょう.このようなGradleファイル
...
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'

android {

   ...

    // Compile options
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = JavaVersion.VERSION_1_8.toString()
    }

}

dependencies {
    ....

    // Preferences DataStore
    implementation "androidx.datastore:datastore-preferences:1.0.0-alpha01"

    // Lifecycle components
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
    implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
    implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0"
    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"

    // Kotlin coroutines components
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72"
    api "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
    api "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9"

    //Dagger - Hilt
    implementation "com.google.dagger:hilt-android:2.28-alpha"
    kapt "com.google.dagger:hilt-android-compiler:2.28-alpha"

}
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {

   ....

    dependencies {
        classpath "com.android.tools.build:gradle:4.0.1"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "com.google.dagger:hilt-android-gradle-plugin:2.28-alpha"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
さて、次のようにアプリケーションクラスのデータストアを作成します
@HiltAndroidApp
class DataStore: Application() {

    override fun onCreate() {
        super.onCreate()
    }

}
次に、すべてのロジックが行くDataManagerクラスを作成します.この例では、ユーザーの名前、githubのユーザー名とお気に入りの番号を格納している
class DataManager(context: Context) {

    private val dataStore = context.createDataStore("data_prefs")

    companion object{
        val USER_NAME = preferencesKey<String>("USER_NAME")
        val USER_GITHUB = preferencesKey<String>("USER_GITHUB")
        val USER_NO = preferencesKey<Int>("USER_NO")
    }

    suspend fun storeData(name:String, github:String, no:Int){
        dataStore.edit {
            it[USER_NAME] = name
            it[USER_GITHUB] = github
            it[USER_NO] = no
        }
    }

    val userNameFlow:Flow<String> = dataStore.data.map {
        it[USER_NAME] ?: ""
    }

    val userGithubFlow:Flow<String> = dataStore.data.map {
        it[USER_GITHUB] ?: ""
    }

    val userNo: Flow<Int> = dataStore.data.map {
        it[USER_NO] ?: -1
    }

}
ここでは、StoreData関数は、非同期にするために中断されます.💛
次に、このDataManagerを提供するAppModuleを作成します
@Module
@InstallIn(ApplicationComponent::class)
object AppModule {

    @Singleton
    @Provides
    fun provideDataManager(@ApplicationContext context: Context) = DataManager(context)

}
これは、我々のアプリケーションにDataManagerのsingletonを提供します
主な活動のレイアウトを次のように作成します.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="#0E0E0E">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:fontFamily="@font/poppins_medium"
        android:text="Data Store Example"
        android:textColor="#fff"
        android:textSize="20sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:id="@+id/tvTitle"/>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvTitle"
        android:backgroundTint="@color/colorPrimary"
        android:textColor="#fff"
        android:hint="Enter name"
        android:textColorHint="#8C8C8C"
        android:fontFamily="@font/poppins_medium"
        android:layout_marginTop="50dp"
        android:layout_marginStart="30dp"
        android:layout_marginEnd="30dp"
        android:id="@+id/etName"/>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/etName"
        android:backgroundTint="@color/colorPrimary"
        android:textColor="#fff"
        android:hint="Github username"
        android:textColorHint="#8C8C8C"
        android:fontFamily="@font/poppins_medium"
        android:layout_marginTop="20dp"
        android:layout_marginStart="30dp"
        android:layout_marginEnd="30dp"
        android:id="@+id/etgithub"/>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/etgithub"
        android:backgroundTint="@color/colorPrimary"
        android:textColor="#fff"
        android:hint="Enter favourite Number"
        android:textColorHint="#8C8C8C"
        android:fontFamily="@font/poppins_medium"
        android:layout_marginTop="20dp"
        android:layout_marginStart="30dp"
        android:layout_marginEnd="30dp"
        android:id="@+id/etNumber"/>

    <com.google.android.material.button.MaterialButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/etNumber"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="20dp"
        android:backgroundTint="@color/colorPrimary"
        app:cornerRadius="25dp"
        android:text="SAVE"
        android:paddingStart="20dp"
        android:paddingEnd="20dp"
        android:textColor="#fff"
        android:id="@+id/btnSave"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/btnSave"
        app:layout_constraintStart_toStartOf="parent"
        android:text="No data saved to display!"
        android:textColor="#fff"
        android:textSize="16sp"
        android:inputType="number"
        android:id="@+id/tvName"
        android:visibility="gone"
        android:fontFamily="@font/poppins_medium"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginTop="30dp"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvName"
        app:layout_constraintStart_toStartOf="parent"
        android:text="No data saved to display!"
        android:textColor="#fff"
        android:textSize="16sp"
        android:visibility="gone"
        android:id="@+id/tvGithub"
        android:fontFamily="@font/poppins_medium"
        app:layout_constraintEnd_toEndOf="parent"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvGithub"
        app:layout_constraintStart_toStartOf="parent"
        android:text="No data saved to display!"
        android:textColor="#fff"
        android:textSize="16sp"
        android:id="@+id/tvNo"
        android:visibility="gone"
        android:fontFamily="@font/poppins_medium"
        app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>
最後にここに私たちの主な活動😌
@AndroidEntryPoint
class MainActivity : AppCompatActivity() {

    @Inject
    lateinit var dataManager: DataManager
    private var name:String = ""
    private var github:String = ""
    private var no:Int = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        subscribeToObservers()

        btnSave.setOnClickListener {
            val name:String = etName.text.toString()
            val github:String = etgithub.text.toString()
            val no:Int = etNumber.text.toString().toInt()

            if (name.isNotEmpty() && github.isNotEmpty() && no!=-1){
                GlobalScope.launch {
                    dataManager.storeData(name,github,no)
                }
            }else{
                Toast.makeText(this, "Enter details carefully!", Toast.LENGTH_SHORT).show()
            }

        }

    }

    private fun subscribeToObservers() {

        dataManager.userNameFlow.asLiveData().observe(this) {
            name = it
            if (name.isNotEmpty()){
                tvName.visibility = View.VISIBLE
                tvName.text = "Name: $name"
            }
        }

        dataManager.userGithubFlow.asLiveData().observe(this) {
            github = it
            if (github.isNotEmpty()){
                tvGithub.visibility = View.VISIBLE
                tvGithub.text = "Github: $github"
            }
        }

        dataManager.userNo.asLiveData().observe(this) {
            no = it
            if (no != -1){
                tvNo.visibility = View.VISIBLE
                tvNo.text = "Number: $no"
            }
        }

    }
}
ここでは、LiveDataとして我々の環境設定キーを見て、それらを見えさせました.
すべては、この実装ではかなり滑らかでまっすぐ進む😌
完全なコードリファレンスチェックアウトのために、このrepository
次の話でお会いしましょう.