توی سال 2021 ورژن پایدار از DataStore منتشر شد. این کتابخونه که جزو کتابخونه های Jetpack هم هست به عنوان راهی جدید برای ذخیره اطلاعات کوچک و جایگزینی برای SharedPreferences معرفی شد.
(نکته: DataStore دو نوع داره : Proto و Preferences . این پست روی پیاده سازی Preferences تمرکز میکنه)
خب اول از همه باید ببینیم چرا نیازه ازش استفاده کنیم . مزایایی که قراره بررسیشون کنیم اینا هستن:
یکی از معایب اصلی SharedPreferences که اتفاقا نقطه قوت DataStore هست اینکه که SharedPreferences عملیاتش رو روی Main Thread اجرا میکنه ، در نتیجه باعث میشه رابط کاربری ما هنگام استفاده ازش بلاک بشه. اما از اون طرف این قضیه برای DataStore کاملا فرق میکنه چون عملیاتش رو با استفاده از قدرت Kotlin Coroutines و Flow به صورت نامتقارن (asynchronous) و در یه Thread جدا (به صورت پیشفرض IO ، البته میتونید تغییرش بدید) اجرا میکنه که باعث میشه رابط کاربری متوقف نشه.
یه مسئله دیگه ای که وجود داره Data Consistency یا سازگاری اطلاعات هستش. توی SharedPreferences چون عملیات به صورت متقارن (synchronous) انجام میشه برای مثال وقتی یه برنامه داریم که چند تا Thread مختلف داره ، ممکنه اطلاعاتمون به درستی ذخیره نشه پس ممکنه اخرین چیزی که ذخیره شده باشه چیزی نباشه که ما انتظار داریم باشه.
حالا DataStore اومده این مشکل رو حل کرده. با استفاده از این میتونید همیشه مطمئن باشید که اطلاعاتی که الان دارید دریافت میکنید اخرین اطلاعاتی هست که ذخیره کردید.
نقطه تفاوت بعدی کنترل خطا (Error handling) هستش. توی SharedPreferences شما احتمال برخورد با کرش رو دارید ولی با استفاده از DataStore که از Flow استفاده میکنه میتونید خطا هایی که پیش میاد رو مدیریت کنید.
علاوه بر همه مزایا که گفته شد، انتقال اطلاعات از SharedPreferences به DataStore خیلی راحته و به آسونی میتونید شروع به استفاده از DataStore بکنید.
خب برای پیاده سازی DataStore اول از همه باید Dependency اش رو نصب کنیم. پس توی فایل app/build.gradle در قسمت dependencies این خط رو اضافه میکنیم:
implementation("androidx.datastore:datastore-preferences:1.0.0")
حالا این فایلو میسازیم:
object DataStoreKeys { private val dataStore = stringPreferencesKey("app") val username = stringPreferencesKey("username") val Context.dataStore by preferencesDataStore (name = dataStore.name) }
توی این فایل اومدیم کلید های DataStore تعریف میکردیم و بعدش هم با استفاده از preferencesDataStore خود DataStore رو ساختیم. و حالا همه چی برای ما آماده استفاده کردنه.
برای خوندن اطلاعات میشه یه همچین چیزی توی activity نوشت:
private suspend fun getName(): String? { val ps = this.dataStore.data.first().toPreferences() return ps[username] }
(دقت کنید this داره به Context اکتیویتی اشاره میکنه)
اینجوری هم میشه اطلاعات رو سیو کرد:
private suspend fun saveName(value: String) { this.dataStore.edit { it[username] = value } }
از اونجایی که این دوتا تابع ما suspend هستن پس باید توی Coroutine Scope اجرا بشن. برای اینکار میشه از lifecycleScope استفاده کرد:
lifecycleScope.launch { saveName("Amir") getName() }
به همین روال میتونید DataStore خودتونو بسازید و ازش استفاده کنید.
اگه توی کداتون از SharedPreferences استفاده میکردید و حالا میخواید همه اطلاعات رو منتقل کنید به DataStore و از این به بعد از DataStore استفاده کنید، کافیه این تغییرو رو توی فایل DataStoreKeys که ساختیمش بدید:
object DataStoreKeys { private val dataStore = stringPreferencesKey("app") val username = stringPreferencesKey("username") val Context.dataStore by preferencesDataStore( name = dataStore.name,
//add this line produceMigrations = { context -> listOf(SharedPreferencesMigration(context, "YOUR_SHARED_PREFERENCES_NAME")) } ) }
فقط کافیه بجای YOUR_SHARED_PREFERENCES_NAME اسم SharedPreferences خودتونو بدید و تموم. به همین راحتی همه اطلاعات به همراه کلید هاشون به DataStore منتقل شدن.
اگه دوست داشتید خوشحال میشم لایک کنید و نظراتتونو کامنت کنید. اگر هم آموزش چیز دیگه ای رو میخواید برای پست بعدی حتما بهم بگید.
اپ جدیدمون هم منتشر کردیم به تازگی، میتونید از اینجا ببینیدش. حمایت هاتون خیلی با ارزشه❤️