ذخیره سازی اطلاعات در آندروید — SharedPreferences

آندروید برای ذخیره سازی اطلاعات راهکارهای مختلفی داره که میشه برای ذخیره وضعیت یا استیت برنامه و یا داده های برنامه از اونا استفاده کرد. اصلی ترین راه هاش این مواردن

تنظیمات اشتراکی که تو این مطلب در موردش صحبت میکنیم

ذخیره فایل و اطلاعات در حافظه اصلی گوشی و حافظه خارجی

ذخیره تو بانک اطلاعاتی رابطه ای که تو خود سیستم عامل پشتیبانی میشه

و نهایتا ذخیره اطلاعات رو وب که از طریق ارتباط شبکه و معمولا سرویس های وب انجام میشه

در این مطلب در مورد اول که گوگل اون رو تنظیمات اشتراکی ترجمه میکنه صحبت میکنیم. البته تو ادامه میبینیم که لزوما اشتراکی نیست. تنظیمات اشتراکی در واقع جاییه برای ذخیره اطلاعاتی که به احتمال زیاد خیلی تغییر نمیکنه و حجمشون هم کمه مثل تنظیمات تم یا نام کاربری البته یادتون باشه این اطلاعات رمزگذاری نمیشن. آندروید این اطلاعات رو تو یک فایل ایکس ام ال و به صورت جفت کلید-مقدار ذخیره میکنه و اجازه میده از طریق واسطی که به شما میده اون اطلاعات رو مدیریت کنید.

سطح دسترسی به این اطلاعات هم میتونه عمومی باشه که همه بتونن اون رو ببینن یا بخونن و هم میتونه خصوصی باشه که در سطح همون اپ یا اکتیویتی قابل دیدن باشه. البته هم توصیه میشه که این اطلاعات خصوصی باشه و از ورژن ۱۷ واسط آندروید حالت عمومی منسوخ شده و تو نسخه های بالاتر آندروید اگر این اطلاعات رو عمومی استفاده کنید بهتون خطا میده

معمولا دو گروه داده ها در این رویکرد ذخیره میشه . یکی اون نوع داده های که نوع های داخلی زبان هستن مثل اعداد صحیح و رشته . و نوع های که توسط کاربر تعریف میشن مثل کلاس ها و مجموعه ها . تو ادامه در مورد جفتشون توضیح میدم

تنظیمات اشتراکی در دو سطح اکتیویتی و اپ ایجاد میشه. وقتی در سطح اکتیویتی باشه صرفا همون اکتیویتی بهش دسترسی داره و یه فایل ایکس ام ال به نام همون اکتیویتی ساخته میشه. وقتی در سطح اپ باشه همه مولفه های اپ میتونن بهش دسترسی داشته باشن. در این حالت اسم فایل باید منحصر به فرد باشه .

مثال زیر ایجاد تنظیمات اشتراکی رو در سطح اکتیویتی نشون میده.

fun saveSharedDara(view: View){
    // file ->MainActivity.xml
    val sharedPreferences = getPreferences(Context.MODE_PRIVATE)
    val editor = sharedPreferences.edit()

    editor.putInt("id", 12)
    editor.putString("name", etName.text.toString())
    editor.putBoolean("flag", true)

    editor.apply()

}

fun loadSharedData(view: View){
    var sharedPreferences = getPreferences(Context.MODE_PRIVATE)


    val id = sharedPreferences.getInt("id", 0)
    val name = sharedPreferences.getString("name", "")
    val flag = sharedPreferences.getBoolean("flag", false)

}

مثال زیر هم برای سطح اپ :

fun saveSharedDara(view: View){
    // file ->MainActivity.xml
    val sharedPreferences = getSharedPreferences("myfile",Context.MODE_PRIVATE)
    val editor = sharedPreferences.edit()

    editor.putInt("id", 12)
    editor.putString("name", etName.text.toString())
    editor.putBoolean("flag", true)

    editor.apply()

}

fun loadSharedData(view: View){
    val sharedPreferences = getSharedPreferences("myfile",Context.MODE_PRIVATE)


    val id = sharedPreferences.getInt("id", 0)
    val name = sharedPreferences.getString("name", "")
    val flag = sharedPreferences.getBoolean("flag", false)

}

از اونجا که این اطلاعات در فایل ایکس ام ال ذخیره میشن قاعدتا محدودیت های برای ذخیره سازی دارن. مثلا چطوری میشه یک شی خاص از مشتری رو ذخیره کرد. برای ذخیره انواع داده ای که به تعبیری انواع داده اولیه در زبان نیستن مثل عدد یا رشته میشه ابجکت مورد نظر رو تبدیل به رشته کرد و اون رو به عنوان متن ذخیره و بازیابی کرد. فقط قبل و بعد این عملیات داده ها رو سریالیزه و دسریالیزه کرد. یکی از رایجترین روش ها برای این کار استفاده از جیسان ه. مثال زیر رو این روش رو نشون میده.

data class User(var name:String, var last:String, val age:Int)
fun saveUserData(view: View){
    val sharedPreferene = getPreferences(Context.MODE_PRIVATE)
    val editor = sharedPreferene.edit()

    val gson = Gson()
    val user = User("heman","hosseinpana", 30 )
    editor.putString("user", gson.toJson(user,User::class.java))

    editor.apply()
}

fun loadUserData(view: View){
    val sharedPreferene = getPreferences(Context.MODE_PRIVATE)

    val gson = Gson()
    val user = gson.fromJson(sharedPreferene.getString("user"),User::class.java))
}

تو این حالت چون نوع اون کلاس باید مشخص باشه وقتی کلاستون جنریک باشه به مشکلی میخورید. برای حل این مساله خود کتابخانه جیسون یه کلاس داره که برای هر نوع یک توکن تولید میکنه:

val token = object: TypeToken<List<User>>(){}.type
editor.putString("users", gson.toJson(users,token))

علاوه بر این مواردی که مطرح شد فریمورک تنظیمات در آندروید امکانات زیادی وجود داره مثلا شما میتونید اکتیویتی و فراگمنت مخصوص تنظیمات در اپ بسازید و اون رو مدیریت کنید و یا برای تغییرات این تظیمات هندلر های خودتون رو بنویسید تا وقتی که تغییر کرد کاری که مدنظرتون هست رو انجام بدید. لینک زیر اطلاعات کاملی از این فریمورک ارایه میده

https://developer.android.com/reference/android/preference/package-summary