0Pricing
Android Academy · درس

تفضيلات DataStore

استبدلوا SharedPreferences بمكتبة DataStore الحديثة. اقرأوا البيانات بصيغة Kotlin Flow، واكتبوها باستخدام edit{}، وتعاملوا مع الأخطاء بأمان.

تفضيلات DataStore درس مجاني في Android Academy على CoddyKit. هذا هو الدرس 5 من أصل 6. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Android Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Android Academy 6 دروس في المجموع.

لماذا DataStore؟

DataStore هو البديل الحديث لـ SharedPreferences. فهو يحل مشكلات حقيقية:

  • يحظر SharedPreferences خيط واجهة المستخدم — أما DataStore فهو غير متزامن بالكامل
  • قد يطرح SharedPreferences استثناءات غير ملتقطة — بينما يعالج DataStore الأخطاء عبر Flow
  • يتمتع DataStore بأمان الأنواع (Preferences) أو أمان المخطط (Proto)
  • يعمل أصليًا مع Kotlin Coroutines وFlow

نوعا DataStore

اختر النوع المناسب لحالة الاستخدام الخاصة بك:

  • Preferences DataStore — أزواج مفتاح-قيمة، ولا يتطلب مخططًا. الأسهل في الإعداد. الأنسب لإعدادات التطبيق وتفضيلات المستخدم.
  • Proto DataStore — كائنات ذات أنواع باستخدام Protocol Buffers. يتطلب ملف مخطط ‎.proto‎. الأنسب عند التعامل مع بيانات منظمة.

يتناول هذا الدرس Preferences DataStore.

إضافة التبعية

أضف DataStore إلى app/build.gradle:

// app/build.gradle
dependencies {
    implementation 'androidx.datastore:datastore-preferences:1.1.1'
    // Coroutines (likely already in your project)
    implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
}

إنشاء مثيل DataStore

أنشئ DataStore مرة واحدة باستخدام المفوض العام. يُجرى ذلك عادةً في ملف مستقل:

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

// Top-level property — creates a single DataStore instance per Context
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "user_prefs")

تعريف المفاتيح

المفاتيح كائنات آمنة النوع، وليست سلاسل نصية عادية. أنشئها باستخدام دالة المصنع المناسبة:

import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey

object PreferencesKeys {
    val DARK_MODE    = booleanPreferencesKey("dark_mode")
    val USER_NAME    = stringPreferencesKey("user_name")
    val LAUNCH_COUNT = intPreferencesKey("launch_count")
}

كتابة البيانات

اكتب داخل coroutine باستخدام edit { }:

import androidx.datastore.preferences.core.edit

// In a ViewModel or Repository:
suspend fun saveDarkMode(enabled: Boolean) {
    context.dataStore.edit { prefs ->
        prefs[PreferencesKeys.DARK_MODE] = enabled
    }
}

suspend fun incrementLaunchCount() {
    context.dataStore.edit { prefs ->
        val current = prefs[PreferencesKeys.LAUNCH_COUNT] ?: 0
        prefs[PreferencesKeys.LAUNCH_COUNT] = current + 1
    }
}

قراءة البيانات باستخدام Flow

يُوفّر DataStore البيانات على هيئة Flow. استخدم map لاستخراج القيمة التي تحتاج إليها:

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

val darkModeFlow: Flow<Boolean> = context.dataStore.data
    .map { prefs ->
        prefs[PreferencesKeys.DARK_MODE] ?: false  // default = false
    }

val userNameFlow: Flow<String> = context.dataStore.data
    .map { prefs ->
        prefs[PreferencesKeys.USER_NAME] ?: "Guest"
    }

جمع البيانات في ViewModel

اعرض Flows الخاصة بـ DataStore من ViewModel باستخدام stateIn لجمعها بكفاءة:

class SettingsViewModel(private val repo: SettingsRepository) : ViewModel() {

    val isDarkMode: StateFlow<Boolean> = repo.darkModeFlow
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5000),
            initialValue = false
        )

    fun toggleDarkMode(enabled: Boolean) {
        viewModelScope.launch {
            repo.saveDarkMode(enabled)
        }
    }
}

المراقبة في Activity/Fragment

اجمع StateFlow في واجهة المستخدم باستخدام lifecycleScope.launch:

// In Fragment:
lifecycleScope.launch {
    viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
        viewModel.isDarkMode.collect { darkMode ->
            binding.switchDarkMode.isChecked = darkMode
            AppCompatDelegate.setDefaultNightMode(
                if (darkMode) AppCompatDelegate.MODE_NIGHT_YES
                else AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
            )
        }
    }
}

معالجة الأخطاء

يُصدر DataStore خطأ IOException إذا كان الملف تالفًا. التقطه في مسار Flow:

import kotlinx.coroutines.flow.catch
import java.io.IOException

val safeFlow: Flow<Boolean> = context.dataStore.data
    .catch { exception ->
        if (exception is IOException) {
            emit(emptyPreferences())   // return defaults
        } else {
            throw exception
        }
    }
    .map { prefs ->
        prefs[PreferencesKeys.DARK_MODE] ?: false
    }

مقارنة DataStore وSharedPreferences

ملخص أسباب تفوق DataStore:

  • يقرأ DataStore البيانات ويكتبها تلقائيًا في خيط خلفي، لذلك لا يوجد خطر ANR
  • قد تفشل apply() في SharedPreferences بصمت، بينما ينشر DataStore الأخطاء عبر Flow
  • DataStore تفاعلي، فتتحدّث واجهة المستخدم تلقائيًا عند تغيّر البيانات
  • لا يوفّر SharedPreferences مسارًا للترحيل، بينما يوفّر DataStore مكوّن SharedPreferencesMigration مضمّنًا

تحقق سريع

ما الآلية الرئيسية التي يستخدمها DataStore لإتاحة بياناته لبقية التطبيق؟

مراجعة: Preferences DataStore

DataStore هو الأسلوب الحديث لحفظ البيانات البسيطة:

  • أضف تبعية datastore-preferences
  • أنشئ مثيلًا واحدًا باستخدام المفوض preferencesDataStore
  • عرّف مفاتيح آمنة النوع باستخدام stringPreferencesKey وbooleanPreferencesKey وغيرهما
  • اكتب باستخدام dataStore.edit { } داخل coroutine
  • اقرأ البيانات على هيئة Flow باستخدام dataStore.data.map { }
  • عالج IOException باستخدام .catch { emit(emptyPreferences()) }

التالي: إنشاء adapters فعّالة للقوائم باستخدام DiffUtil.

الأسئلة الشائعة

هل درس «تفضيلات DataStore» مجاني؟

نعم — نص درس «تفضيلات DataStore» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Android Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Android Academy 6 دروس في المجموع.

ماذا ستتعلم في «تفضيلات DataStore»؟

استبدلوا SharedPreferences بمكتبة DataStore الحديثة. اقرأوا البيانات بصيغة Kotlin Flow، واكتبوها باستخدام edit{}، وتعاملوا مع الأخطاء بأمان. تتمرن على Android Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ Android Academy؟

لا تُشترط خبرة سابقة. Android Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 5 من أصل 6.

كم من الوقت يستغرق درس «تفضيلات DataStore»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس Android Academy هذا؟

نعم. كل درس في Android Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. مجموعات Kotlin
  2. أساسيات RecyclerView
  3. أحداث النقر في RecyclerView
  4. SharedPreferences
  5. تفضيلات DataStore
  6. Adapters وDiffUtil
← العودة إلى Android Academy