0Pricing
Kotlin Academy · บทเรียน

ตัวแทนสำหรับ Preferences พร็อพเพอร์ตีที่ใช้ Map และการบันทึก

ประยุกต์ใช้ตัวแทนกับ SharedPreferences การจัดเก็บด้วย Map และการบันทึกเพื่อตรวจสอบ

ตัวแทนสำหรับ Preferences พร็อพเพอร์ตีที่ใช้ Map และการบันทึก เป็นบทเรียน Kotlin Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Kotlin Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

พร็อพเพอร์ตีที่ใช้แมปเป็นแหล่งข้อมูลเบื้องหลัง

Kotlin อนุญาตให้มอบหมายพร็อพเพอร์ตีให้กับ Map ได้โดยตรง การอ่านพร็อพเพอร์ตีจะค้นหาชื่อของพร็อพเพอร์ตีในแมป

class User(map: Map<String, Any?>) {
    val name: String by map
    val age: Int by map
}
fun main() {
    val u = User(mapOf("name" to "Alice", "age" to 30))
    println(u.name) // Alice
    println(u.age)  // 30
}

ดีลีต MutableMap

สำหรับพร็อพเพอร์ตีที่เปลี่ยนแปลงได้ ให้มอบหมายไปยัง MutableMap แล้วการเปลี่ยนแปลงจะอัปเดตแมปที่อยู่เบื้องหลัง

class Settings(private val map: MutableMap<String, Any?> = mutableMapOf()) {
    var theme: String by map
    var fontSize: Int by map
}
fun main() {
    val s = Settings()
    s.theme = "dark"
    s.fontSize = 16
    println(s.theme)    // dark
    println(s.fontSize) // 16
}

การดีซีเรียลไลซ์ JSON ด้วยดีลีตแมป

แยกวิเคราะห์แมปที่มีลักษณะคล้าย JSON แล้วเปิดเผยฟิลด์ต่าง ๆ เป็นพร็อพเพอร์ตีที่มีชนิดข้อมูล โดยใช้การมอบหมายให้แมป เหมาะอย่างยิ่งสำหรับข้อมูลแบบไดนามิก

class ApiResponse(data: Map<String, Any?>) {
    val id: Int by data
    val title: String by data
    val published: Boolean by data
}
fun main() {
    val response = ApiResponse(mapOf("id" to 1, "title" to "Kotlin Rocks", "published" to true))
    println(response.title)     // Kotlin Rocks
    println(response.published) // true
}

รูปแบบดีลีตสำหรับการบันทึกข้อมูลการทำงาน

ห่อดีลีตใด ๆ ด้วยการบันทึกข้อมูลการทำงาน เพื่อ ติดตามการอ่านและการเขียนทุกครั้งอย่างโปร่งใสในพร็อพเพอร์ตีที่ได้รับการมอบหมายทั้งหมด

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class Logged<T>(private var v: T) : ReadWriteProperty<Any?, T> {
    override fun getValue(t: Any?, p: KProperty<*>): T {
        println("[READ]  ${p.name} = $v"); return v
    }
    override fun setValue(t: Any?, p: KProperty<*>, value: T) {
        println("[WRITE] ${p.name}: $v -> $value"); v = value
    }
}
var config: String by Logged("default")
fun main() { println(config); config = "production" }

การรวมแมปกับการบันทึกข้อมูลการทำงาน

วางตัวห่อสำหรับการบันทึกข้อมูลการทำงานไว้รอบการมอบหมายให้แมป เพื่อให้ตรวจสอบการเข้าถึงพร็อพเพอร์ตีแบบไดนามิกได้อย่างครบถ้วน

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class TrackedMap(private val map: MutableMap<String,Any?> = mutableMapOf()) {
    inner class Delegate<T> : ReadWriteProperty<Any?,T> {
        @Suppress("UNCHECKED_CAST")
        override fun getValue(t:Any?,p:KProperty<*>): T {
            val v = map[p.name] as T; println("read ${p.name}=$v"); return v
        }
        override fun setValue(t:Any?,p:KProperty<*>,value:T) {
            println("write ${p.name}=$value"); map[p.name]=value
        }
    }
    var host: String by Delegate()
}
fun main() { val m=TrackedMap(); m.host="localhost"; println(m.host) }

ดีลีตลักษณะเดียวกับ SharedPreferences

ดีลีตที่จัดเก็บค่าไว้ในแมปเบื้องหลังเพื่อจำลอง SharedPreferences โดยสามารถปรับใช้กับการตั้งค่าจริงของ Android ได้ด้วยการเปลี่ยนแมปเป็นการเรียกใช้การตั้งค่าจริง

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
val prefs = mutableMapOf<String, Any?>()
fun <T> pref(default: T): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
    @Suppress("UNCHECKED_CAST")
    override fun getValue(t: Any?, p: KProperty<*>): T = prefs.getOrDefault(p.name, default) as T
    override fun setValue(t: Any?, p: KProperty<*>, value: T) { prefs[p.name] = value }
}
object UserPrefs {
    var username: String by pref("Guest")
    var isDarkMode: Boolean by pref(false)
}
fun main() {
    println(UserPrefs.username)   // Guest
    UserPrefs.username = "Alice"
    println(UserPrefs.username)   // Alice
}

ฟังก์ชันช่วยจัดการการตั้งค่าที่มีชนิดข้อมูล

สร้างฟังก์ชันช่วยที่มีชนิดข้อมูลเฉพาะสำหรับการตั้งค่าพื้นฐานแต่ละชนิด เพื่อให้จุดเรียกใช้สะอาดและอ่านง่ายขึ้น

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
val store = mutableMapOf<String,Any?>()
fun stringPref(default: String) = object : ReadWriteProperty<Any?,String> {
    @Suppress("UNCHECKED_CAST")
    override fun getValue(t:Any?,p:KProperty<*>) = store.getOrDefault(p.name, default) as String
    override fun setValue(t:Any?,p:KProperty<*>,v:String) { store[p.name]=v }
}
fun intPref(default: Int) = object : ReadWriteProperty<Any?,Int> {
    @Suppress("UNCHECKED_CAST")
    override fun getValue(t:Any?,p:KProperty<*>) = store.getOrDefault(p.name, default) as Int
    override fun setValue(t:Any?,p:KProperty<*>,v:Int) { store[p.name]=v }
}
object Prefs {
    var name: String by stringPref("default")
    var count: Int by intPref(0)
}
fun main() { Prefs.name="Bob"; Prefs.count=5; println("${Prefs.name}: ${Prefs.count}") }

ดีลีตบันทึกการตรวจสอบ

บันทึกการเปลี่ยนแปลงพร็อพเพอร์ตีทุกครั้งพร้อมเวลาประทับลงในรายการบันทึกการตรวจสอบ เหมาะสำหรับสถานการณ์ที่ต้องปฏิบัติตามข้อกำหนดหรือการแก้ไขข้อบกพร่อง

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
val audit = mutableListOf<String>()
class AuditDelegate<T>(private var v: T) : ReadWriteProperty<Any?, T> {
    override fun getValue(t:Any?,p:KProperty<*>) = v
    override fun setValue(t:Any?,p:KProperty<*>,value:T) {
        audit += "[${System.currentTimeMillis()}] ${p.name}: $v -> $value"
        v = value
    }
}
var price: Double by AuditDelegate(9.99)
fun main() {
    price = 12.99
    price = 11.49
    audit.forEach(::println)
}

การตรวจสอบความถูกต้องร่วมกับการจัดเก็บในแมป

ผสานการจัดเก็บในแมปเข้ากับการตรวจสอบความถูกต้อง โดยปฏิเสธค่าที่ไม่ถูกต้องก่อนเขียนลงในแมป

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
val data = mutableMapOf<String, Any?>()
fun positiveInt(default: Int): ReadWriteProperty<Any?,Int> = object : ReadWriteProperty<Any?,Int> {
    @Suppress("UNCHECKED_CAST")
    override fun getValue(t:Any?,p:KProperty<*>)=data.getOrDefault(p.name,default) as Int
    override fun setValue(t:Any?,p:KProperty<*>,v:Int){
        require(v>=0){"${p.name} must be >= 0"}
        data[p.name]=v
    }
}
object Inventory { var stock: Int by positiveInt(100) }
fun main(){
    Inventory.stock=50; println(Inventory.stock)
    try { Inventory.stock=-1 } catch(e:Exception){ println(e.message) }
}

รูปแบบการประกอบดีลีต

ประกอบพฤติกรรมของดีลีตหลายรายการโดยใช้ API ลักษณะเดียวกับตัวสร้าง เริ่มจากดีลีตพื้นฐาน แล้วเพิ่มการบันทึกข้อมูลการทำงาน การตรวจสอบความถูกต้อง หรือการแคชทีละชั้น

import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
fun <T> ReadWriteProperty<Any?,T>.withLogging(): ReadWriteProperty<Any?,T> {
    val base = this
    return object : ReadWriteProperty<Any?,T> {
        override fun getValue(t:Any?,p:KProperty<*>): T {
            val v = base.getValue(t,p); println("get ${p.name}=$v"); return v
        }
        override fun setValue(t:Any?,p:KProperty<*>,v:T){
            println("set ${p.name}=$v"); base.setValue(t,p,v)
        }
    }
}

การใช้งานจริง: รูปแบบออบเจ็กต์การตั้งค่า

ใช้การมอบหมายให้แมปเพื่อสร้างออบเจ็กต์การตั้งค่าจากแหล่งข้อมูลภายนอก เช่น ตัวแปรสภาพแวดล้อมหรือไฟล์การตั้งค่า JSON

class AppConfig(private val raw: Map<String, Any?>) {
    val host: String by raw
    val port: Int by raw
    val debug: Boolean by raw
}
fun main() {
    val env = mapOf("host" to "0.0.0.0", "port" to 8080, "debug" to true)
    val cfg = AppConfig(env)
    println("${cfg.host}:${cfg.port} debug=${cfg.debug}")
}

ตรวจสอบความเข้าใจ

จะเกิดอะไรขึ้นเมื่อคุณมอบหมายพร็อพเพอร์ตีให้กับ Map

สรุปทบทวน

ดีลีตช่วยให้ใช้รูปแบบที่ทรงพลังได้หลายแบบ ได้แก่ การมอบหมายให้แมปสำหรับข้อมูลแบบไดนามิกหรือ JSON การคงอยู่ของข้อมูลในลักษณะ SharedPreferences การบันทึกการตรวจสอบเพื่อรองรับข้อกำหนด และการตรวจสอบความถูกต้องที่ประกอบใช้งานได้ โดยไม่ต้องเปลี่ยนจุดเรียกใช้

คำถามที่พบบ่อย

บทเรียน “ตัวแทนสำหรับ Preferences พร็อพเพอร์ตีที่ใช้ Map และการบันทึก” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ตัวแทนสำหรับ Preferences พร็อพเพอร์ตีที่ใช้ Map และการบันทึก” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Kotlin Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Kotlin Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ตัวแทนสำหรับ Preferences พร็อพเพอร์ตีที่ใช้ Map และการบันทึก”

ประยุกต์ใช้ตัวแทนกับ SharedPreferences การจัดเก็บด้วย Map และการบันทึกเพื่อตรวจสอบ คุณปฏิบัติ Kotlin Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Kotlin Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Kotlin Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “ตัวแทนสำหรับ Preferences พร็อพเพอร์ตีที่ใช้ Map และการบันทึก” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Kotlin Academy นี้ได้ไหม

ได้ บทเรียน Kotlin Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. by lazy: เจาะลึกการเริ่มต้นแบบเลื่อนเวลา
  2. ตัวแทน observable และ vetoable
  3. การเขียนตัวแทน ReadWriteProperty แบบกำหนดเอง
  4. ตัวแทนสำหรับ Preferences พร็อพเพอร์ตีที่ใช้ Map และการบันทึก
← กลับไปที่ Kotlin Academy