Android KTX เป็นส่วนหนึ่งของ Android Jetpack
Android KTX คือชุดส่วนขยาย Kotlin ที่มาพร้อมกับ Android Jetpack และไลบรารีอื่นๆ ของ Android ส่วนขยาย KTX ช่วยให้ Kotlin สั้นกระชับและเป็นธรรมชาติสำหรับ Jetpack, แพลตฟอร์ม Android และ API อื่นๆ โดยส่วนขยายเหล่านี้ใช้ประโยชน์จากฟีเจอร์ภาษา Kotlin หลายอย่าง ซึ่งรวมถึงฟีเจอร์ต่อไปนี้
- ฟังก์ชันส่วนขยาย
- พร็อพเพอร์ตี้ส่วนขยาย
- แลมดา
- พารามิเตอร์ที่มีชื่อ
- ค่าเริ่มต้นของพารามิเตอร์
- Coroutine
ตัวอย่างเช่น เมื่อทํางานกับ SharedPreferences
คุณต้องสร้างเครื่องมือแก้ไขก่อนจึงจะแก้ไขข้อมูลค่ากําหนดได้ นอกจากนี้ คุณยังต้องใช้หรือทําการเปลี่ยนแปลงเหล่านั้นเมื่อแก้ไขเสร็จแล้ว ดังที่แสดงในตัวอย่างต่อไปนี้
sharedPreferences
.edit() // create an Editor
.putBoolean("key", value)
.apply() // write to disk asynchronously
แลมดาของ Kotlin เหมาะอย่างยิ่งสําหรับกรณีการใช้งานนี้ ซึ่งช่วยให้คุณใช้แนวทางที่กระชับยิ่งขึ้นได้ด้วยการส่งบล็อกโค้ดเพื่อเรียกใช้หลังจากที่สร้างเครื่องมือแก้ไขแล้ว ปล่อยให้โค้ดทำงาน จากนั้นให้ SharedPreferences
API ใช้การเปลี่ยนแปลงแบบเป็นกลุ่ม
ต่อไปนี้คือตัวอย่างฟังก์ชันหลักของ Android KTX รายการหนึ่ง ซึ่งก็คือ SharedPreferences.edit
ซึ่งจะเพิ่มฟังก์ชันแก้ไขลงใน SharedPreferences
ฟังก์ชันนี้ใช้ Flag boolean
(ไม่บังคับ) เป็นอาร์กิวเมนต์แรก ซึ่งระบุว่าจะคอมมิตหรือใช้การเปลี่ยนแปลงหรือไม่ นอกจากนี้ ยังได้รับการดำเนินการที่จะทำในเครื่องมือแก้ไข SharedPreferences
ในรูปแบบของ Lambda ด้วย
// SharedPreferences.edit extension function signature from Android KTX - Core
// inline fun SharedPreferences.edit(
// commit: Boolean = false,
// action: SharedPreferences.Editor.() -> Unit)
// Commit a new value asynchronously
sharedPreferences.edit { putBoolean("key", value) }
// Commit a new value synchronously
sharedPreferences.edit(commit = true) { putBoolean("key", value) }
ผู้โทรสามารถเลือกที่จะคอมมิตหรือใช้การเปลี่ยนแปลงได้ action
lambda เป็นฟังก์ชันส่วนขยายที่ไม่ระบุชื่อใน SharedPreferences.Editor
ซึ่งแสดงผล Unit
ตามที่ระบุไว้ในลายเซ็น ด้วยเหตุนี้ คุณจึงทํางานใน SharedPreferences.Editor
ได้โดยตรงภายในบล็อก
สุดท้ายคือลายเซ็น SharedPreferences.edit()
มีคีย์เวิร์ด inline
คีย์เวิร์ดนี้บอกคอมไพเลอร์ Kotlin ว่าควรคัดลอกและวาง (หรือแทรก) บิตโค้ดที่คอมไพล์แล้วสำหรับฟังก์ชันทุกครั้งที่มีการใช้ฟังก์ชัน
วิธีนี้จะช่วยหลีกเลี่ยงค่าใช้จ่ายเพิ่มเติมในการสร้างอินสแตนซ์ของคลาสใหม่สำหรับ action
แต่ละรายการทุกครั้งที่มีการเรียกใช้ฟังก์ชันนี้
รูปแบบการส่งโค้ดโดยใช้ Lambda, การใช้ค่าเริ่มต้นที่เหมาะสมซึ่งสามารถลบล้างได้ และการเพิ่มลักษณะการทำงานเหล่านี้ลงใน API ที่มีอยู่โดยใช้inline
ฟังก์ชันส่วนขยายเป็นลักษณะการเพิ่มประสิทธิภาพที่ไลบรารี KTX ของ Android มีให้
ใช้ Android KTX ในโปรเจ็กต์
หากต้องการเริ่มใช้ Android KTX ให้เพิ่มการพึ่งพาต่อไปนี้ลงในไฟล์ build.gradle
ของโปรเจ็กต์
Groovy
repositories { google() }
Kotlin
repositories { google() }
โมดูล AndroidX
Android KTX จัดระเบียบเป็นโมดูล โดยแต่ละโมดูลจะมีแพ็กเกจอย่างน้อย 1 รายการ
คุณต้องระบุทรัพยากร Dependency ของอาร์ติแฟกต์โมดูลแต่ละรายการในไฟล์ build.gradle
ของแอป อย่าลืมใส่หมายเลขเวอร์ชันต่อท้ายอาร์ติแฟกต์
คุณดูหมายเลขเวอร์ชันล่าสุดได้ในส่วนที่เกี่ยวข้องของอาร์ติแฟกต์แต่ละรายการในหัวข้อนี้
Android KTX มีโมดูลหลักโมดูลเดียวที่ให้บริการส่วนขยาย Kotlin สําหรับ API เฟรมเวิร์กทั่วไปและส่วนขยายเฉพาะโดเมนหลายรายการ
อาร์ติแฟกต์ของโมดูล KTX ทั้งหมดจะแทนที่การพึ่งพา Java พื้นฐานในไฟล์ build.gradle
ยกเว้นโมดูลหลัก เช่น คุณสามารถแทนที่ androidx.fragment:fragment
Dependency ด้วย androidx.fragment:fragment-ktx
รูปแบบคำสั่งนี้ช่วยจัดการการกำหนดเวอร์ชันได้ดียิ่งขึ้นและจะไม่เพิ่มข้อกำหนดในการประกาศการพึ่งพาเพิ่มเติม
Core KTX
โมดูล Core KTX มีส่วนขยายสําหรับไลบรารีทั่วไปซึ่งเป็นส่วนหนึ่งของเฟรมเวิร์ก Android ไลบรารีเหล่านี้ไม่มีทรัพยากร Dependency ที่ใช้ Java ซึ่งคุณต้องเพิ่มลงใน build.gradle
หากต้องการรวมโมดูลนี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "androidx.core:core-ktx:1.15.0" }
Kotlin
dependencies { implementation("androidx.core:core-ktx:1.15.0") }
ต่อไปนี้คือรายการแพ็กเกจที่อยู่ในโมดูล KTX หลัก
- androidx.core.animation
- androidx.core.content
- androidx.core.content.res
- androidx.core.database
- androidx.core.database.sqlite
- androidx.core.graphics
- androidx.core.graphics.drawable
- androidx.core.location
- androidx.core.net
- androidx.core.os
- androidx.core.text
- androidx.core.transition
- androidx.core.util
- androidx.core.view
- androidx.core.widget
Collection KTX
ส่วนขยายคอลเล็กชันประกอบด้วยฟังก์ชันยูทิลิตีสำหรับทํางานกับคลังคอลเล็กชันที่ประหยัดหน่วยความจําของ Android ซึ่งรวมถึง ArrayMap
, LongSparseArray
, LruCache
และอื่นๆ
หากต้องการใช้โมดูลนี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "androidx.collection:collection-ktx:1.4.5" }
Kotlin
dependencies { implementation("androidx.collection:collection-ktx:1.4.5") }
ส่วนขยายคอลเล็กชันใช้ประโยชน์จากการโอเวอร์โหลดโอเปอเรเตอร์ของ Kotlin เพื่อลดความซับซ้อนของการดำเนินการต่างๆ เช่น การต่อคอลเล็กชัน ดังตัวอย่างต่อไปนี้
// Combine 2 ArraySets into 1.
val combinedArraySet = arraySetOf(1, 2, 3) + arraySetOf(4, 5, 6)
// Combine with numbers to create a new sets.
val newArraySet = combinedArraySet + 7 + 8
KTX ของ Fragment
โมดูล KTX ของ FRGMENT มีส่วนขยายหลายรายการเพื่อลดความซับซ้อนของ FRGMENT API
หากต้องการรวมโมดูลนี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "androidx.fragment:fragment-ktx:1.8.5" }
Kotlin
dependencies { implementation("androidx.fragment:fragment-ktx:1.8.5") }
โมดูล KTX ของส่วนช่วยให้คุณทําธุรกรรมของส่วนย่อยได้ง่ายขึ้นด้วยแลมบดา เช่น
fragmentManager().commit {
addToBackStack("...")
setCustomAnimations(
R.anim.enter_anim,
R.anim.exit_anim)
add(fragment, "...")
}
นอกจากนี้ คุณยังเชื่อมโยงกับ ViewModel
ในบรรทัดเดียวได้โดยใช้ตัวรับช่วงพร็อพเพอร์ตี้ viewModels
และ activityViewModels
ดังนี้
// Get a reference to the ViewModel scoped to this Fragment
val viewModel by viewModels<MyViewModel>()
// Get a reference to the ViewModel scoped to its Activity
val viewModel by activityViewModels<MyViewModel>()
Lifecycle KTX
KTX วงจรชีวิตของแอปจะกำหนด LifecycleScope
สำหรับออบเจ็กต์ Lifecycle
แต่ละรายการ โคโริวทีนที่เริ่มทำงานในสโกปนี้จะยกเลิกเมื่อ Lifecycle
ถูกทำลาย คุณสามารถเข้าถึง CoroutineScope
ของ Lifecycle
โดยใช้พร็อพเพอร์ตี้ lifecycle.coroutineScope
หรือ lifecycleOwner.lifecycleScope
หากต้องการรวมโมดูลนี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.8.7" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7") }
ตัวอย่างต่อไปนี้แสดงวิธีใช้ lifecycleOwner.lifecycleScope
เพื่อสร้างข้อความที่ประมวลผลล่วงหน้าแบบไม่พร้อมกัน
class MyFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
val params = TextViewCompat.getTextMetricsParams(textView)
val precomputedText = withContext(Dispatchers.Default) {
PrecomputedTextCompat.create(longTextContent, params)
}
TextViewCompat.setPrecomputedText(textView, precomputedText)
}
}
}
LiveData KTX
เมื่อใช้ LiveData คุณอาจต้องคํานวณค่าแบบไม่พร้อมกัน เช่น คุณอาจต้องการเรียกข้อมูลค่ากําหนดของผู้ใช้และแสดงใน UI ในกรณีเหล่านี้ LiveData KTX มีliveData
ฟังก์ชันตัวสร้างที่เรียกใช้ฟังก์ชัน suspend
และแสดงผลลัพธ์เป็นออบเจ็กต์ LiveData
หากต้องการรวมโมดูลนี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.8.7" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.8.7") }
ในตัวอย่างต่อไปนี้ loadUser()
คือฟังก์ชันการระงับที่ประกาศไว้ที่อื่น
คุณสามารถใช้ฟังก์ชันบิลเดอร์ liveData
เพื่อเรียก loadUser()
แบบไม่พร้อมกัน แล้วใช้ emit()
เพื่อแสดงผลลัพธ์
val user: LiveData<User> = liveData {
val data = database.loadUser() // loadUser is a suspend function.
emit(data)
}
ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ Coroutines กับ LiveData
ได้ที่
ใช้ Coroutines ของ Kotlin กับคอมโพเนนต์สถาปัตยกรรม
Navigation KTX
คอมโพเนนต์แต่ละรายการของไลบรารีการนำทางมีเวอร์ชัน KTX ของตัวเองซึ่งปรับ API ให้กระชับและเป็นรูปแบบ Kotlin มากขึ้น
หากต้องการรวมโมดูลเหล่านี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "androidx.navigation:navigation-runtime-ktx:2.8.5" implementation "androidx.navigation:navigation-fragment-ktx:2.8.5" implementation "androidx.navigation:navigation-ui-ktx:2.8.5" }
Kotlin
dependencies { implementation("androidx.navigation:navigation-runtime-ktx:2.8.5") implementation("androidx.navigation:navigation-fragment-ktx:2.8.5") implementation("androidx.navigation:navigation-ui-ktx:2.8.5") }
ใช้ฟังก์ชันส่วนขยายและการมอบสิทธิ์พร็อพเพอร์ตี้เพื่อเข้าถึงอาร์กิวเมนต์ปลายทางและไปยังปลายทาง ดังที่แสดงในตัวอย่างต่อไปนี้
class MyDestination : Fragment() {
// Type-safe arguments are accessed from the bundle.
val args by navArgs<MyDestinationArgs>()
...
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
view.findViewById<Button>(R.id.next)
.setOnClickListener {
// Fragment extension added to retrieve a NavController from
// any destination.
findNavController().navigate(R.id.action_to_next_destination)
}
}
...
}
Palette KTX
โมดูล Palette KTX รองรับรูปแบบโค้ด Kotlin สำหรับการทำงานกับชุดสี
หากต้องการใช้โมดูลนี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "androidx.palette:palette-ktx:1.0.0" }
Kotlin
dependencies { implementation("androidx.palette:palette-ktx:1.0.0") }
ตัวอย่างเช่น เมื่อทํางานกับอินสแตนซ์ Palette
คุณสามารถเรียกข้อมูลตัวอย่างสี selected
ของ target
หนึ่งๆ โดยใช้โอเปอเรเตอร์ get ([ ]
) ดังนี้
val palette = Palette.from(bitmap).generate()
val swatch = palette[target]
Reactive Streams KTX
โมดูล Reactive Streams KTX ช่วยให้คุณสร้างLiveData
สตรีมแบบสังเกตการณ์จากReactiveStreams
ผู้เผยแพร่โฆษณาได้
หากต้องการรวมโมดูลนี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:2.8.7" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-reactivestreams-ktx:2.8.7") }
ตัวอย่างเช่น สมมติว่าฐานข้อมูลมีรายชื่อผู้ใช้เพียงไม่กี่รายการ ในแอป คุณจะโหลดฐานข้อมูลลงในหน่วยความจำ จากนั้นแสดงข้อมูลผู้ใช้ใน UI คุณอาจใช้ RxJava เพื่อให้บรรลุเป้าหมายนี้
คอมโพเนนต์ Room
ของ Jetpack สามารถดึงข้อมูลรายการผู้ใช้เป็น Flowable
ได้ ในสถานการณ์นี้ คุณต้องจัดการการสมัครใช้บริการ Rx ของผู้เผยแพร่โฆษณาตลอดอายุของข้อมูลโค้ดหรือกิจกรรมด้วย
อย่างไรก็ตาม เมื่อใช้ LiveDataReactiveStreams
คุณจะได้รับประโยชน์จาก RxJava และชุดโอเปอเรเตอร์ที่หลากหลาย รวมถึงความสามารถในการกำหนดเวลาทำงานไปพร้อมๆ กับความเรียบง่ายของ LiveData
ดังที่แสดงในตัวอย่างต่อไปนี้
val fun getUsersLiveData() : LiveData<List<User>> {
val users: Flowable<List<User>> = dao.findUsers()
return LiveDataReactiveStreams.fromPublisher(users)
}
Room KTX
ส่วนส่วนขยายของ Room จะเพิ่มการรองรับ coroutines สำหรับธุรกรรมฐานข้อมูล
หากต้องการใช้โมดูลนี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "androidx.room:room-ktx:2.6.1" }
Kotlin
dependencies { implementation("androidx.room:room-ktx:2.6.1") }
ต่อไปนี้เป็นตัวอย่างบางส่วนที่ Room ใช้ coroutine ในปัจจุบัน ตัวอย่างแรกใช้ฟังก์ชัน suspend
เพื่อแสดงรายการออบเจ็กต์ User
ส่วนตัวอย่างที่ 2 ใช้ Flow
ของ Kotlin เพื่อแสดงรายการ User
แบบไม่พร้อมกัน โปรดทราบว่าเมื่อใช้ Flow
คุณจะได้รับการแจ้งเตือนเกี่ยวกับการเปลี่ยนแปลงในตารางที่คุณค้นหาด้วย
@Query("SELECT * FROM Users")
suspend fun getUsers(): List<User>
@Query("SELECT * FROM Users")
fun getUsers(): Flow<List<User>>
SQLite KTX
ส่วนขยาย SQLite จะรวมโค้ดที่เกี่ยวข้องกับ SQL ไว้ในธุรกรรม ซึ่งจะช่วยลดโค้ดที่ซ้ำกันจำนวนมาก
หากต้องการใช้โมดูลนี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "androidx.sqlite:sqlite-ktx:2.4.0" }
Kotlin
dependencies { implementation("androidx.sqlite:sqlite-ktx:2.4.0") }
ตัวอย่างการใช้ส่วนขยาย transaction
เพื่อดําเนินธุรกรรมฐานข้อมูลมีดังนี้
db.transaction {
// insert data
}
ViewModel KTX
ไลบรารี ViewModel KTX มีฟังก์ชัน viewModelScope()
ที่ช่วยให้คุณเปิด Coroutine จาก ViewModel
ได้ง่ายขึ้น CoroutineScope
เชื่อมโยงกับ Dispatchers.Main
และยกเลิกโดยอัตโนมัติเมื่อล้าง ViewModel
คุณสามารถใช้ viewModelScope()
แทนการสร้างขอบเขตใหม่สําหรับ ViewModel
แต่ละรายการ
หากต้องการรวมโมดูลนี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7" }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.7") }
ตัวอย่างเช่น ฟังก์ชัน viewModelScope()
ต่อไปนี้จะเปิดใช้ coroutine ที่ส่งคำขอเครือข่ายในเธรดแบ็กกราวด์ ไลบรารีจะจัดการการตั้งค่าทั้งหมดและการล้างขอบเขตที่เกี่ยวข้อง
class MainViewModel : ViewModel() {
// Make a network request without blocking the UI thread
private fun makeNetworkRequest() {
// launch a coroutine in viewModelScope
viewModelScope.launch {
remoteApi.slowFetch()
...
}
}
// No need to override onCleared()
}
WorkManager KTX
WorkManager KTX รองรับโคโริวทีนอย่างเต็มรูปแบบ
หากต้องการรวมโมดูลนี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "androidx.work:work-runtime-ktx:2.9.1" }
Kotlin
dependencies { implementation("androidx.work:work-runtime-ktx:2.9.1") }
ตอนนี้คุณขยาย CoroutineWorker
ได้แทนการขยาย Worker
ซึ่งมี API ที่แตกต่างออกไปเล็กน้อย เช่น หากต้องการสร้าง CoroutineWorker
ง่ายๆ เพื่อดําเนินการบางอย่างกับเครือข่าย ให้ทําดังนี้
class CoroutineDownloadWorker(context: Context, params: WorkerParameters)
: CoroutineWorker(context, params) {
override suspend fun doWork(): Result = coroutineScope {
val jobs = (0 until 100).map {
async {
downloadSynchronously("https://www.google.com")
}
}
// awaitAll will throw an exception if a download fails, which
// CoroutineWorker will treat as a failure
jobs.awaitAll()
Result.success()
}
}
ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ CoroutineWorker
ได้ที่การแยก Thread ใน CoroutineWorker
นอกจากนี้ WorkManager KTX ยังเพิ่มฟังก์ชันส่วนขยายลงใน Operations
และ
ListenableFutures
เพื่อระงับโคโรทีนิวปัจจุบัน
ต่อไปนี้คือตัวอย่างที่ระงับ Operation
ที่แสดงผลโดย enqueue()
// Inside of a coroutine...
// Run async operation and suspend until completed.
WorkManager.getInstance()
.beginWith(longWorkRequest)
.enqueue().await()
// Resume after work completes...
โมดูล KTX อื่นๆ
นอกจากนี้ คุณยังรวมโมดูล KTX เพิ่มเติมที่อยู่นอก AndroidX ได้ด้วย
Firebase KTX
Firebase SDK บางรายการสําหรับ Android มีไลบรารีส่วนขยาย Kotlin ที่ช่วยให้คุณเขียนโค้ด Kotlin ได้ตามแบบแผนเมื่อใช้ Firebase ในแอป ดูข้อมูลเพิ่มเติมได้ที่หัวข้อต่อไปนี้
KTX ของ Google Maps Platform
เรามีส่วนขยาย KTX สำหรับ SDK ของ Google Maps Platform สำหรับ Android ซึ่งจะช่วยให้คุณใช้ประโยชน์จากฟีเจอร์ต่างๆ ของภาษา Kotlin ได้ เช่น ฟังก์ชันส่วนขยาย พารามิเตอร์ที่มีชื่อและอาร์กิวเมนต์เริ่มต้น การประกาศแบบแยกโครงสร้าง และโคโริวทีน ดูข้อมูลเพิ่มเติมได้ที่หัวข้อต่อไปนี้
Play Core KTX
Play Core KTX เพิ่มการรองรับโคโริวทีน Kotlin สำหรับคำขอแบบดำเนินการครั้งเดียวและ Flow สำหรับการตรวจสอบการอัปเดตสถานะโดยการเพิ่มฟังก์ชันส่วนขยายลงใน SplitInstallManager
และ AppUpdateManager
ในไลบรารี Play Core
หากต้องการรวมโมดูลนี้ ให้เพิ่มค่าต่อไปนี้ลงในไฟล์ build.gradle
ของแอป
Groovy
dependencies { implementation "com.google.android.play:core-ktx:1.8.1" }
Kotlin
dependencies { implementation("com.google.android.play:core-ktx:1.8.1") }
ตัวอย่าง Flow
ที่ใช้ตรวจสอบสถานะมีดังนี้
// Inside of a coroutine...
// Request in-app update status updates.
manager.requestUpdateFlow().collect { updateResult ->
when (updateResult) {
is AppUpdateResult.Available -> TODO()
is AppUpdateResult.InProgress -> TODO()
is AppUpdateResult.Downloaded -> TODO()
AppUpdateResult.NotAvailable -> TODO()
}
}
ข้อมูลเพิ่มเติม
ดูข้อมูลเพิ่มเติมเกี่ยวกับ Android KTX ได้ในวิดีโอ DevBytes
หากต้องการรายงานปัญหาหรือแนะนำฟีเจอร์ ให้ใช้เครื่องมือติดตามปัญหา Android KTX