DataStore   بخشی از Android Jetpack.

با Kotlin چندپلاتفرمی امتحان کنید
‫Kotlin چندپلاتفرمی امکان هم‌رسانی لایه داده با پلاتفرم‌های دیگر را فراهم می‌کند. با نحوه راه‌اندازی و کار کردن با DataStore در KMP آشنا شوید

‫Jetpack DataStore راه‌حلی برای ذخیره داده است که به شما امکان می‌دهد جفت‌های کلید-مقدار یا اشیای تایپ‌شده را با بافرهای پروتکل ذخیره کنید. ‫DataStore از Kotlin coroutines و Flow برای ذخیره داده‌ها به‌صورت ناهم‌زمان، یکپارچه، و تراکنشی استفاده می‌کند.

اگر از SharedPreferences برای ذخیره داده‌ها استفاده می‌کنید، به DataStore انتقال دهید.

DataStore API

میانای DataStore میانای برنامه‌سازی کاربردی زیر را ارائه می‌دهد:

  1. جریانی که می‌تواند برای خواندن داده‌ها از DataStore استفاده شود

    val data: Flow<T>
    
  2. تابعی برای به‌روزرسانی داده‌ها در DataStore

    suspend updateData(transform: suspend (t) -> T)
    

پیکربندی‌های DataStore

اگر می‌خواهید داده‌ها را بااستفاده از کلیدها ذخیره و به آن‌ها دسترسی پیدا کنید، از پیاده‌سازی Preferences DataStore استفاده کنید که به طرحواره ازپیش تعریف‌شده نیاز ندارد و ایمنی نوع را ارائه نمی‌دهد. این ویژگی یک API شبیه به SharedPreferences دارد اما معایب مربوط به اولویت‌های مشترک را ندارد.

‫DataStore به شما امکان می‌دهد کلاس‌های سفارشی را ماندگار کنید. برای انجام این کار، باید طرحواره‌ای برای داده‌ها تعریف کنید و Serializer را برای تبدیل آن به قالب ماندگار ارائه دهید. می‌توانید انتخاب کنید که از «بافرهای پروتکل»،‏ JSON، یا هر استراتژی سریال‌سازی دیگری استفاده کنید.

راه‌اندازی

برای استفاده از Jetpack DataStore در برنامه‌تان، موارد زیر را به فایل Gradle اضافه کنید بسته به اینکه می‌خواهید از کدام پیاده‌سازی استفاده کنید:

فروشگاه داده تنظیمات

خطوط زیر را به بخش وابستگی‌های فایل gradle خود اضافه کنید:

گرووی

    dependencies {
        // Preferences DataStore (SharedPreferences like APIs)
        implementation "androidx.datastore:datastore-preferences:1.2.1"

        // Alternatively - without an Android dependency.
        implementation "androidx.datastore:datastore-preferences-core:1.2.1"
    }
    

کاتلین

    dependencies {
        // Preferences DataStore (SharedPreferences like APIs)
        implementation("androidx.datastore:datastore-preferences:1.2.1")

        // Alternatively - without an Android dependency.
        implementation("androidx.datastore:datastore-preferences-core:1.2.1")
    }
    

برای افزودن پشتیبانی اختیاری از RxJava، وابستگی‌های زیر را اضافه کنید:

گرووی

    dependencies {
        // optional - RxJava2 support
        implementation "androidx.datastore:datastore-preferences-rxjava2:1.2.1"

        // optional - RxJava3 support
        implementation "androidx.datastore:datastore-preferences-rxjava3:1.2.1"
    }
    

کاتلین

    dependencies {
        // optional - RxJava2 support
        implementation("androidx.datastore:datastore-preferences-rxjava2:1.2.1")

        // optional - RxJava3 support
        implementation("androidx.datastore:datastore-preferences-rxjava3:1.2.1")
    }
    

فروشگاه داده

خطوط زیر را به بخش وابستگی‌های فایل gradle خود اضافه کنید:

گرووی

    dependencies {
        // Typed DataStore for custom data objects (for example, using Proto or JSON).
        implementation "androidx.datastore:datastore:1.2.1"

        // Alternatively - without an Android dependency.
        implementation "androidx.datastore:datastore-core:1.2.1"
    }
    

کاتلین

    dependencies {
        // Typed DataStore for custom data objects (for example, using Proto or JSON).
        implementation("androidx.datastore:datastore:1.2.1")

        // Alternatively - without an Android dependency.
        implementation("androidx.datastore:datastore-core:1.2.1")
    }
    

وابستگی‌های اختیاری زیر را برای پشتیبانی از RxJava اضافه کنید:

گرووی

    dependencies {
        // optional - RxJava2 support
        implementation "androidx.datastore:datastore-rxjava2:1.2.1"

        // optional - RxJava3 support
        implementation "androidx.datastore:datastore-rxjava3:1.2.1"
    }
    

کاتلین

    dependencies {
        // optional - RxJava2 support
        implementation("androidx.datastore:datastore-rxjava2:1.2.1")

        // optional - RxJava3 support
        implementation("androidx.datastore:datastore-rxjava3:1.2.1")
    }
    

برای سریال‌سازی محتوا، وابستگی‌هایی را برای Protocol Buffers یا سریال‌سازی JSON اضافه کنید.

سریال‌سازی JSON

برای استفاده از سریال‌سازی JSON، موارد زیر را به فایل Gradle خود اضافه کنید:

گرووی

    plugins {
        id("org.jetbrains.kotlin.plugin.serialization") version "2.2.20"
    }

    dependencies {
        implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0"
    }
    

کاتلین

    plugins {
        id("org.jetbrains.kotlin.plugin.serialization") version "2.2.20"
    }

    dependencies {
        implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0")
    }
    

سریال‌سازی پروتوباف

برای استفاده از سریال‌سازی Protobuf، موارد زیر را به فایل Gradle خود اضافه کنید:

گرووی

    plugins {
        id("com.google.protobuf") version "0.9.5"
    }
    dependencies {
        implementation "com.google.protobuf:protobuf-kotlin-lite:4.32.1"

    }

    protobuf {
        protoc {
            artifact = "com.google.protobuf:protoc:4.32.1"
        }
        generateProtoTasks {
            all().forEach { task ->
                task.builtins {
                    create("java") {
                        option("lite")
                    }
                    create("kotlin")
                }
            }
        }
    }
    

کاتلین

    plugins {
        id("com.google.protobuf") version "0.9.5"
    }
    dependencies {
        implementation("com.google.protobuf:protobuf-kotlin-lite:4.32.1")
    }

    protobuf {
        protoc {
            artifact = "com.google.protobuf:protoc:4.32.1"
        }
        generateProtoTasks {
            all().forEach { task ->
                task.builtins {
                    create("java") {
                        option("lite")
                    }
                    create("kotlin")
                }
            }
        }
    }
    

استفاده صحیح از DataStore

برای استفاده صحیح از DataStore، همیشه قوانین زیر را به‌خاطر داشته باشید:

  1. هرگز بیش‌از یک نمونه از DataStore برای فایل معینی در فرایند یکسان ایجاد نکنید. انجام این کار می‌تواند باعث ازکار افتادن همه عملکردهای DataStore شود. اگر چندین DataStore برای یک فایل معین در یک فرایند فعال باشند، DataStore هنگام خواندن یا به‌روزرسانی داده‌ها IllegalStateException را پرتاب می‌کند.

  2. نوع عمومی DataStore<T> باید تغییرناپذیر باشد. تغییر دادن نوعی که در DataStore استفاده می‌شود، سازگاری‌ای را که DataStore ارائه می‌دهد نامعتبر می‌کند و اشکالات بالقوه جدی و دشوار برای شناسایی ایجاد می‌کند. توصیه می‌کنیم از بافرهای پروتکل استفاده کنید که به تضمین تغییرناپذیری، API واضح، و سریال‌سازی کارآمد کمک می‌کند.

  3. کاربردهای SingleProcessDataStore و MultiProcessDataStore را برای یک فایل ترکیب نکنید. اگر قصد دارید از بیش‌از یک فرایند به DataStore دسترسی پیدا کنید، باید از MultiProcessDataStore استفاده کنید.

تعریف داده‌ها

‫Preferences DataStore

کلیدی را تعریف کنید که برای ماندگار کردن داده‌ها در دیسک استفاده خواهد شد.

val EXAMPLE_COUNTER = intPreferencesKey("example_counter")

‫JSON DataStore

برای مخزن داده JSON، یک گزارمان @Serialization به داده‌هایی که می‌خواهید ماندگار شوند اضافه کنید.

@Serializable data class Settings(val exampleCounter: Int)

کلاسی را تعریف کنید که Serializer<T> را پیاده‌سازی می‌کند، که در آن T نوع کلاسی است که گزارمان را قبلاً به آن اضافه کرده‌اید. مطمئن شوید که مقدار پیش‌فرضی را برای سریال‌ساز اضافه کنید تا درصورتی‌که هنوز فایلی ایجاد نشده باشد از آن استفاده شود.

object SettingsSerializer : Serializer<Settings> {

    override val defaultValue: Settings = Settings(exampleCounter = 0)

    override suspend fun readFrom(input: InputStream): Settings =
        try {
            Json.decodeFromString(Settings.serializer(), input.readBytes().decodeToString())
        } catch (serialization: SerializationException) {
            throw CorruptionException("Unable to read Settings", serialization)
        }

    override suspend fun writeTo(t: Settings, output: OutputStream) {
        output.write(Json.encodeToString(Settings.serializer(), t).encodeToByteArray())
    }
}

Proto DataStore

پیاده‌سازی Proto DataStore از DataStore و بافرهای پروتکل برای ماندگار کردن اشیای نوع‌دار در دیسک استفاده می‌کند.

‫Proto DataStore به طرحواره‌ای ازپیش تعریف‌شده در فایل proto در دایرکتوری app/src/main/proto/ نیاز دارد. این طرحواره نوع اشیایی را که در Proto DataStore ذخیره می‌کنید تعریف می‌کند. برای کسب اطلاعات بیشتر درباره تعریف کردن طرحواره proto، به راهنمای زبان protobuf مراجعه کنید.

فایلی به‌نام settings.proto را به پوشه src/main/proto اضافه کنید:

syntax = "proto3";

option java_package = "com.example.datastoresampleapp";
option java_multiple_files = true;

message Settings {
  int32 counter = 1;
  bool foo = 2;
}

کلاسی را تعریف کنید که Serializer<T> را پیاده‌سازی می‌کند، که در آن T نوع تعریف‌شده در فایل proto است. این کلاس سریال‌ساز تعریف می‌کند که DataStore چگونه نوع داده شما را می‌خواند و می‌نویسد. مطمئن شوید که مقدار پیش‌فرضی برای سریال‌ساز اضافه کنید تا درصورتی‌که هنوز فایلی ایجاد نشده است استفاده شود.

object SettingsSerializer : Serializer<Settings> {
    override val defaultValue: Settings = Settings.getDefaultInstance()

    override suspend fun readFrom(input: InputStream): Settings {
        try {
            return Settings.parseFrom(input)
        } catch (exception: InvalidProtocolBufferException) {
            throw CorruptionException("Cannot read proto.", exception)
        }
    }

    override suspend fun writeTo(t: Settings, output: OutputStream) {
        return t.writeTo(output)
    }
}

ایجاد DataStore

باید نامی برای فایلی که برای ماندگار کردن داده‌ها استفاده می‌شود مشخص کنید.

‫Preferences DataStore

پیاده‌سازی Preferences DataStore از کلاس‌های DataStore و Preferences برای ماندگار کردن جفت‌های کلید-مقدار در دیسک استفاده می‌کند. برای ایجاد نمونه‌ای از DataStore<Preferences>، از نماینده دارایی ایجادشده توسط preferencesDataStore استفاده کنید. آن را یک‌بار در سطح بالای فایل Kotlin خود فراخوانی کنید. ازطریق این دارایی در بقیه برنامه‌تان به DataStore دسترسی داشته باشید. این کار باعث می‌شود که DataStore را راحت‌تر به‌عنوان تک‌نمونه نگه دارید. پارامتر اجباری name نام Preferences DataStore است.

// At the top level of your kotlin file:
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "settings")

‫JSON DataStore

برای ایجاد نمونه‌ای از DataStore<T>، که در آن T کلاس داده سریال‌شدنی است، از نماینده دارایی ایجادشده توسط dataStore استفاده کنید. آن را یک‌بار در سطح بالای فایل Kotlin خود فراخوانی کنید و ازطریق این نماینده دارایی در سراسر بقیه برنامه به آن دسترسی پیدا کنید. پارامتر fileName به DataStore می‌گوید از کدام فایل برای ذخیره داده‌ها استفاده کند و پارامتر serializer نام کلاس سریال‌ساز تعریف‌شده قبلی را به DataStore می‌گوید.

val Context.dataStore: DataStore<Settings> by
    dataStore(
        fileName = "settings.json",
        serializer = SettingsSerializer,
        scope = CoroutineScope(Dispatchers.IO + SupervisorJob()),
    )

Proto DataStore

از نماینده دارایی ایجادشده توسط dataStore برای ایجاد نمونه‌ای از DataStore<T> استفاده کنید، که در آن T نوع تعریف‌شده در فایل پروتکل است. آن را یک‌بار در سطح بالای فایل Kotlin خود فراخوانی کنید و ازطریق این نماینده دارایی در بقیه برنامه خود به آن دسترسی پیدا کنید. پارامتر fileName به DataStore می‌گوید از کدام فایل برای ذخیره داده‌ها استفاده کند و پارامتر serializer نام کلاس سریال‌ساز تعریف‌شده قبلی را به DataStore می‌گوید.

val Context.dataStore: DataStore<Settings> by
    dataStore(fileName = "settings.pb", serializer = SettingsSerializer)

خواندن از DataStore

باید نامی برای فایلی که برای ماندگار کردن داده‌ها استفاده می‌شود مشخص کنید.

‫Preferences DataStore

ازآنجایی‌که Preferences DataStore از طرحواره ازپیش تعریف‌شده استفاده نمی‌کند، باید از تابع نوع کلید مربوطه برای تعریف کلید هر مقداری که باید در نمونه DataStore<Preferences> ذخیره کنید استفاده کنید. برای مثال، برای تعریف کلید برای مقدار int، از intPreferencesKey استفاده کنید. سپس از دارایی DataStore.data برای آشکار کردن مقدار ذخیره‌شده مناسب بااستفاده از جریان استفاده کنید.

fun counterFlow(): Flow<Int> =
    context.dataStore.data.map { preferences -> preferences[EXAMPLE_COUNTER] ?: 0 }

‫JSON DataStore

از DataStore.data برای آشکار کردن Flow دارایی مناسب از شیء ذخیره‌شده استفاده کنید.

fun counterFlow(): Flow<Int> =
    context.dataStore.data.map { settings -> settings.exampleCounter }

Proto DataStore

از DataStore.data برای آشکار کردن Flow دارایی مناسب از شیء ذخیره‌شده استفاده کنید.

fun counterFlow(): Flow<Int> = context.dataStore.data.map { settings -> settings.counter }

از collectAsStateWithLifecycle برای مصرف Flow تولیدشده توسط ‫ViewModel در یک عنصر ترکیبی استفاده کنید. این تابع «جریان DataStore» را به‌طور ایمن به «حالت Compose» تبدیل می‌کند که باعث بازترکیب می‌شود.

@Composable
fun SomeScreen(counterFlow: Flow<Int>) {
  val counter by counterFlow.collectAsStateWithLifecycle(initialValue = 0)
  Text(text = "Example counter: ${counter}")
}

برای اطلاعات بیشتر درباره collectAsStateWithLifecycle، به حالت و Jetpack Compose مراجعه کنید.

نوشتن در DataStore

‫DataStore تابع updateData را ارائه می‌دهد که به‌صورت تراکنشی شیء ذخیره‌شده را به‌روزرسانی می‌کند. ‫updateData وضعیت فعلی داده‌ها را به‌عنوان نمونه‌ای از نوع داده شما ارائه می‌دهد و داده‌ها را به‌صورت تراکنشی در عملیات خواندن-نوشتن-اصلاح اتمی به‌روز می‌کند. تمام کد موجود در بلوک updateData به‌عنوان یک تراکنش واحد درنظر گرفته می‌شود.

‫Preferences DataStore

suspend fun incrementCounter() {
    context.dataStore.updateData {
        it.toMutablePreferences().also { preferences ->
            preferences[EXAMPLE_COUNTER] = (preferences[EXAMPLE_COUNTER] ?: 0) + 1
        }
    }
}

‫JSON DataStore

suspend fun incrementCounter() {
    context.dataStore.updateData { settings ->
        settings.copy(exampleCounter = settings.exampleCounter + 1)
    }
}

Proto DataStore

suspend fun incrementCounter() {
    context.dataStore.updateData { settings ->
        settings.toBuilder().setCounter(settings.counter + 1).build()
    }
}

استفاده از DataStore در برنامه Compose

برای استفاده از DataStore در برنامه Compose، با نگه داشتن عملیات DataStore در لایه داده (مثل مخزن) و نمایان کردن داده‌ها در واسط کاربر ازطریق ViewModel، از دستورالعمل‌های معماری برنامه Android پیروی کنید.

از خواندن یا نوشتن مستقیم در DataStore در توابع ترکیبی خود اجتناب کنید.

  1. ‫DataStore را ازطریق ViewModel نمایان کنید. مخزن خود (که DataStore را می‌پیچد) را به ViewModel منتقل کنید و Flow را به StateFlow تبدیل کنید تا واسط کاربر بتواند آن را مشاهده کند، همان‌طور که در تکه کد زیر نشان داده شده است:

    class SettingsViewModel(
        private val userPreferencesRepository: UserPreferencesRepository
    ) : ViewModel() {
    
        // Expose the DataStore flow as a StateFlow for Compose
        val userSettings: StateFlow<UserSettings> = userPreferencesRepository.userSettingsFlow
            .stateIn(
                scope = viewModelScope,
                started = SharingStarted.WhileSubscribed(5000),
                initialValue = UserSettings.getDefaultInstance()
            )
    
        fun updateCounter(newValue: Int) {
            viewModelScope.launch {
                userPreferencesRepository.updateCounter(newValue)
            }
        }
    }
    
  2. از عنصر ترکیبی خود مشاهده و بنویسید. از collectAsStateWithLifecycle برای مشاهده ایمن StateFlow در واسط کاربر خود استفاده کنید، و برای مدیریت نوشتن‌ها، همان‌طور که در گزیده زیر نشان داده شده است، توابع ViewModel را فراخوانی کنید:

    @Composable
    fun SettingsScreen(
        viewModel: SettingsViewModel = viewModel()
    ) {
        // Safely collect the state
        val settings by viewModel.userSettings.collectAsStateWithLifecycle()
    
        Column(modifier = Modifier.padding(16.dp)) {
            Text(text = "Current counter: ${settings.counter}")
    
            Spacer(modifier = Modifier.height(8.dp))
    
            Button(onClick = { viewModel.updateCounter(settings.counter + 1) }) {
                Text("Increment Counter")
            }
        }
    }
    

استفاده از DataStore در کد چندپردازشی

می‌توانید DataStore را پیکربندی کنید تا در فرایندهای مختلف به داده‌های یکسانی دسترسی داشته باشد با همان ویژگی‌های سازگاری داده که در یک فرایند واحد وجود دارد. به‌طور خاص، DataStore ویژگی‌های زیر را ارائه می‌دهد:

  • خواندن‌ها فقط داده‌هایی را برمی‌گرداند که در دیسک ماندگار شده‌اند.
  • سازگاری خواندن پس‌از نوشتن.
  • نوشتن‌ها سریال‌سازی می‌شوند.
  • نوشتن هرگز خواندن را مسدود نمی‌کند.

برنامه نمونه‌ای را درنظر بگیرید که سرویس و فعالیتی دارد که در آن سرویس در فرایندی جداگانه اجرا می‌شود و DataStore را به‌صورت دوره‌ای به‌روزرسانی می‌کند.

این مثال از یک فروشگاه داده JSON استفاده می‌کند، اما می‌توانید از Preferences یا Proto DataStore نیز استفاده کنید.

@Serializable data class Time(val lastUpdateMillis: Long)

سریال‌ساز به DataStore می‌گوید چگونه نوع داده‌هایتان را بخواند و بنویسد. مطمئن شوید مقدار پیش‌فرضی را برای سریال‌ساز اضافه کنید تا درصورت عدم وجود فایل ایجادشده استفاده شود. در زیر، پیاده‌سازی نمونه‌ای بااستفاده از kotlinx.serialization ارائه شده است:

object TimeSerializer : Serializer<Time> {

    override val defaultValue: Time = Time(lastUpdateMillis = 0L)

    override suspend fun readFrom(input: InputStream): Time =
        try {
            Json.decodeFromString(Time.serializer(), input.readBytes().decodeToString())
        } catch (serialization: SerializationException) {
            throw CorruptionException("Unable to read Time", serialization)
        }

    override suspend fun writeTo(t: Time, output: OutputStream) {
        output.write(Json.encodeToString(Time.serializer(), t).encodeToByteArray())
    }
}

برای اینکه بتوانید از DataStore در فرایندهای مختلف استفاده کنید، باید شیء DataStore را بااستفاده از MultiProcessDataStoreFactory برای هم برنامه و هم کد سرویس بسازید:

val dataStore =
    MultiProcessDataStoreFactory.create(
        serializer = TimeSerializer,
        produceFile = { context.dataStoreFile("time.pb") },
        corruptionHandler = null,
    )

مورد زیر را به AndroidManifiest.xml اضافه کنید:

<service
    android:name="com.example.datastore.snippets.TimestampUpdateService"
    android:exported="false"
    android:process=":service" />

این سرویس به‌صورت دوره‌ای updateLastUpdateTime را فراخوانی می‌کند که بااستفاده از updateData در انبار داده می‌نویسد.

suspend fun updateLastUpdateTime() {
    dataStore.updateData { time -> time.copy(lastUpdateMillis = System.currentTimeMillis()) }
}

برنامه مقدار نوشته‌شده توسط سرویس را بااستفاده از جریان داده می‌خواند:

fun timeFlow(): Flow<Long> = dataStore.data.map { time -> time.lastUpdateMillis }

اکنون می‌توانیم همه این توابع را در کلاسی به‌نام MultiProcessDataStore قرار دهیم و از آن در «برنامه» استفاده کنیم.

کد سرویس در اینجا است:

class TimestampUpdateService : Service() {
    val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
    val multiProcessDataStore by lazy { MultiProcessDataStore(applicationContext) }


    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        serviceScope.launch {
            while (true) {
                multiProcessDataStore.updateLastUpdateTime()
                delay(1000)
            }
        }
        return START_NOT_STICKY
    }

    override fun onDestroy() {
        super.onDestroy()
        serviceScope.cancel()
    }
}

و کد برنامه:

val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
val multiProcessDataStore = remember(context) { MultiProcessDataStore(context) }

// Display time written by other process.
val lastUpdateTime by
    multiProcessDataStore
        .timeFlow()
        .collectAsState(initial = 0, coroutineScope.coroutineContext)
Text(text = "Last updated: $lastUpdateTime", fontSize = 25.sp)

DisposableEffect(context) {
    val serviceIntent = Intent(context, TimestampUpdateService::class.java)
    context.startService(serviceIntent)
    onDispose { context.stopService(serviceIntent) }
}

می‌توانید از تزریق وابستگی Hilt استفاده کنید تا نمونه DataStore شما برای هر فرایند یکتا باشد:

@Provides
@Singleton
fun provideDataStore(@ApplicationContext context: Context): DataStore<Settings> =
   MultiProcessDataStoreFactory.create(...)

رسیدگی به خرابی فایل

در موارد نادر، ممکن است فایل دائمی روی دیسک DataStore خراب شود. به‌طور پیش‌فرض، DataStore به‌طور خودکار از خرابی بازیابی نمی‌شود، و تلاش برای خواندن از آن باعث می‌شود سیستم CorruptionException را پرتاب کند.

‫DataStore یک API مدیریت خرابی ارائه می‌دهد که می‌تواند به شما کمک کند در چنین شرایطی به‌طور مناسب بازیابی کنید و از ایجاد استثنا جلوگیری کنید. وقتی پیکربندی شود، مدیر خرابی فایل خراب را با فایل جدیدی که حاوی مقدار پیش‌فرض ازپیش‌تعیین‌شده است جایگزین می‌کند.

برای راه‌اندازی این مدیریت‌کننده، هنگام ایجاد نمونه DataStore در by dataStore یا در روش کارخانه DataStoreFactory، corruptionHandler را ارائه دهید:

val dataStore: DataStore<Settings> = DataStoreFactory.create(
   serializer = SettingsSerializer(),
   produceFile = {
       File("${context.filesDir.path}/myapp.preferences_pb")
   },
   corruptionHandler = ReplaceFileCorruptionHandler { Settings(lastUpdate = 0) }
)

پشتیبان‌گیری و بازیابی دستگاه

فایل‌های Preferences DataStore (*.preferences_pb) و فایل‌های Proto DataStore در دایرکتوری files/datastore/ برنامه ذخیره می‌شوند. به‌طور پیش‌فرض، این فایل‌ها در پشتیبان‌گیری خودکار Android و انتقال دستگاه به دستگاه (D2D) گنجانده می‌شوند.

پیکربندی قوانین پشتیبان‌گیری برای DataStore

اگر DataStore شما درکنار داده‌های حساس حاوی اولویت‌های غیرحساس (مثل زمینه کاربر یا پرچم‌های ویژگی) است، آن‌ها را در فایل‌های DataStore متمایز جدا کنید و res/xml/data_extraction_rules.xml را پیکربندی کنید:

<data-extraction-rules>
    <cloud-backup>
        <!-- Include general settings -->
        <include domain="file" path="datastore/user_settings.preferences_pb"/>
        <!-- Exclude sensitive local state -->
        <exclude domain="file" path="datastore/secure_state.preferences_pb"/>
    </cloud-backup>
    <device-to-device>
        <!-- Transfer settings during device-to-device transfer -->
        <include domain="file" path="datastore/"/>
    </device-to-device>
</data-extraction-rules>

ارائه کردن بازخورد

ازطریق این منابع، بازخوردها و ایده‌هایتان را با ما هم‌رسانی کنید:

ردیاب مشکل:
مشکلات را گزارش دهید تا بتوانیم اشکالات را برطرف کنیم.

منابع بیشتر

برای کسب اطلاعات بیشتر درباره Jetpack DataStore، منابع تکمیلی زیر را ببینید:

نمونه‌ها

وبلاگ‌ها

Codelabs