ภาพรวม
บทความนี้แสดงวิธีใช้ SharedPreferences เพื่อส่งข้อมูลระหว่าง Activity สองหน้า วิธีนี้เหมาะสำหรับข้อมูลเล็กน้อยที่ต้องการความต่อเนื่อง (Persistent) แตกต่างจาก Intent ที่ข้อมูลจะหายเมื่อ Process ถูก Kill
หมายเหตุ: เนื้อหานี้คล้ายคลึงกับบทความก่อนหน้า (ID: 1004061530) แต่เน้นที่กรณีใช้งาน "ส่งข้อมูลระหว่าง Activity" โดยเฉพาะ
ตัวอย่างโค้ดสรุป (Kotlin - แนะนำสำหรับโปรเจกต์ใหม่)
MainActivity.kt
package com.example.myapplication
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private val PREF_NAME = "myKey"
private val KEY_VALUE = "value"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener {
val value = edit_text.text.toString().trim()
// บันทึกข้อมูล
val sharedPref = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
sharedPref.edit().putString(KEY_VALUE, value).apply()
startActivity(Intent(this, SecondActivity::class.java))
}
}
}
SecondActivity.kt
package com.example.myapplication
import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_second.*
class SecondActivity : AppCompatActivity() {
private val PREF_NAME = "myKey"
private val KEY_VALUE = "value"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)
val sharedPreferences = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
val value = sharedPreferences.getString(KEY_VALUE, "")
text_view.text = "ข้อมูล: $value"
}
}
แนวทางปฏิบัติที่ดี (Best Practices)
1. ใช้ Constant สำหรับ Key
object PrefKeys {
const val PREF_NAME = "app_preferences"
const val USER_TOKEN = "user_token"
const val USER_NAME = "user_name"
const val IS_LOGGED_IN = "is_logged_in"
}
2. สร้าง Helper Class จัดการ SharedPreferences แบบกลาง
class PreferenceManager(private val context: Context) {
private val prefs: SharedPreferences = context.getSharedPreferences(PrefKeys.PREF_NAME, Context.MODE_PRIVATE)
fun saveString(key: String, value: String) = prefs.edit().putString(key, value).apply()
fun getString(key: String, default: String = ""): String = prefs.getString(key, default)!!
fun saveBoolean(key: String, value: Boolean) = prefs.edit().putBoolean(key, value).apply()
fun getBoolean(key: String, default: Boolean = false): Boolean = prefs.getBoolean(key, default)
// เพิ่มเมธอดอื่นๆ ตามต้องการ
}
3. ใช้ Dependency Injection (Hilt/Koin) เพื่อให้ทดสอบได้ง่าย
เมื่อไหร่ควรใช้ SharedPreferences แทน Intent?
| สถานการณ์ | วิธีที่แนะนำ |
|---|---|
| ส่งข้อมูลชั่วคราวระหว่าง Activity (หน้าต่อหน้า) | Intent + Bundle |
| ข้อมูลที่ต้องคงอยู่หลังปิดแอป (Token, Settings) | SharedPreferences / DataStore |
| ข้อมูลที่หลาย Activity ต้องเข้าถึงร่วมกัน | SharedPreferences / DataStore / ViewModel |
| ข้อมูลขนาดใหญ่ / โครงสร้างซับซ้อน | Room Database / FileStorage |
ย้ายสู่ DataStore (แนะนำสำหรับโปรเจกต์ใหม่)
Google แนะนำให้ย้ายจาก SharedPreferences ไป Jetpack DataStore ซึ่งมี 2 รูปแบบ:
- Preferences DataStore: Key-Value แบบ Async ใช้ Coroutines/Flow (แทน SharedPreferences)
- Proto DataStore: ใช้ Protocol Buffers สำหรับข้อมูลที่มี Schema ชัดเจน
ตัวอย่าง Preferences DataStore
// build.gradle
implementation "androidx.datastore:datastore-preferences:1.0.0"
// ใช้งาน
val Context.dataStore: DataStore<Preferences> by preferencesDataStore("settings")
val EXAMPLE_COUNTER = intPreferencesKey("example_counter")
// เขียน
suspend fun incrementCounter() {
context.dataStore.edit { settings ->
val current = settings[EXAMPLE_COUNTER] ?: 0
settings[EXAMPLE_COUNTER] = current + 1
}
}
// อ่าน (เป็น Flow)
val counterFlow: Flow<Int> = context.dataStore.data
.map { preferences -> preferences[EXAMPLE_COUNTER] ?: 0 }
สรุป
- SharedPreferences ใช้งานง่าย เหมาะข้อมูลเล็ก และ Legacy code
- โปรเจกต์ใหม่ควรใช้ Preferences DataStore
- ใช้ Constant key และ Helper class เพื่อลด Bug
- หลีกเลี่ยงการเก็บข้อมูลละเอียดอ่อน (Password, Token) โดยไม่เข้ารหัส