Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีส่งข้อมูลระหว่าง Activity ด้วย SharedPreferences ใน Android

ภาพรวม

บทความนี้แสดงวิธีใช้ 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) โดยไม่เข้ารหัส