สร้าง ViewModel ที่มี Dependency   ส่วนหนึ่งของ Android Jetpack

ViewModel สามารถใช้ทรัพยากร Dependency เป็นพารามิเตอร์ในตัวสร้างได้ตามแนวทางปฏิบัติแนะนำของการแทรก Dependency โดยส่วนใหญ่จะเป็นประเภท จากชั้นโดเมนหรือข้อมูล เนื่องจากเฟรมเวิร์กมี ViewModel จึงต้องใช้กลไกพิเศษในการสร้างอินสแตนซ์ของ ViewModel กลไกดังกล่าวคืออินเทอร์เฟซ ViewModelProvider.Factory มีเพียงการใช้งาน ของอินเทอร์เฟซนี้เท่านั้นที่สามารถสร้างอินสแตนซ์ ViewModel ในขอบเขตที่ถูกต้องได้

ViewModel ที่มี CreationExtras

หากViewModelคลาสได้รับทรัพยากร Dependency ในตัวสร้าง ให้ระบุ Factory ที่ใช้ViewModelProvider.Factoryอินเทอร์เฟซ แทนที่ฟังก์ชัน create(Class<T>, CreationExtras) เพื่อระบุอินสแตนซ์ใหม่ของ ViewModel

CreationExtras ช่วยให้คุณเข้าถึงข้อมูลที่เกี่ยวข้องซึ่งช่วย สร้างอินสแตนซ์ ViewModel รายการคีย์ที่เข้าถึงได้จากส่วนพิเศษมีดังนี้

คีย์ ฟังก์ชันการทำงาน
ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY ให้สิทธิ์เข้าถึงคีย์ที่กำหนดเองที่คุณส่งไปยัง ViewModelProvider.get()
ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY ให้สิทธิ์เข้าถึงอินสแตนซ์ของคลาส Application
SavedStateHandleSupport.DEFAULT_ARGS_KEY ให้สิทธิ์เข้าถึงกลุ่มอาร์กิวเมนต์ที่คุณควรใช้เพื่อสร้าง SavedStateHandle
SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY ให้สิทธิ์เข้าถึง SavedStateRegistryOwner ที่ใช้สร้าง ViewModel
SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY ให้สิทธิ์เข้าถึง ViewModelStoreOwner ที่ใช้สร้าง ViewModel

หากต้องการสร้างอินสแตนซ์ใหม่ของ SavedStateHandle ให้ใช้ฟังก์ชัน CreationExtras.createSavedStateHandle() และส่งไปยัง ViewModel

CreationExtras ที่มี APPLICATION_KEY

ตัวอย่างต่อไปนี้แสดงวิธีระบุอินสแตนซ์ของ ViewModel ที่ใช้ repository ที่กำหนดขอบเขตไว้ที่คลาส Application และ SavedStateHandle เป็นทรัพยากร Dependency

    import androidx.lifecycle.SavedStateHandle
    import androidx.lifecycle.ViewModel
    import androidx.lifecycle.ViewModelProvider
    import androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion.APPLICATION_KEY
    import androidx.lifecycle.createSavedStateHandle
    import androidx.lifecycle.viewmodel.initializer
    import androidx.lifecycle.viewmodel.viewModelFactory

    class MyViewModel(
        private val myRepository: MyRepository,
        private val savedStateHandle: SavedStateHandle
    ) : ViewModel() {

        // ViewModel logic
        // ...

        // Define ViewModel factory in a companion object
        companion object {

            val Factory: ViewModelProvider.Factory = viewModelFactory {
                initializer {
                    val savedStateHandle = createSavedStateHandle()
                    val myRepository = (this[APPLICATION_KEY] as MyApplication).myRepository
                    MyViewModel(
                        myRepository = myRepository,
                        savedStateHandle = savedStateHandle
                    )
                }
            }
        }
    }

จากนั้นคุณจะใช้ Factory นี้เมื่อเรียกข้อมูลอินสแตนซ์ของ ViewModel ได้

import androidx.lifecycle.viewmodel.compose.viewModel

@Composable
fun MyScreen(
    modifier: Modifier = Modifier,
    viewModel: MyViewModel = viewModel(factory = MyViewModel.Factory)
) {
    // ...
}

ส่งพารามิเตอร์ที่กำหนดเองเป็น CreationExtras

คุณส่งการอ้างอิงไปยัง ViewModel ผ่าน CreationExtras ได้โดยการสร้างคีย์ที่กำหนดเอง ซึ่งจะเป็นประโยชน์หาก ViewModel ขึ้นอยู่กับออบเจ็กต์ที่เข้าถึงไม่ได้ผ่านคลาส Application และ APPLICATION_KEY ตัวอย่างของ กรณีนี้คือเมื่อสร้าง ViewModel ภายในโมดูล Kotlin Multiplatform และจึงไม่มีสิทธิ์เข้าถึงการอ้างอิงของ Android

ในตัวอย่างนี้ ViewModel จะกำหนดคีย์ที่กำหนดเองและใช้คีย์ดังกล่าวใน ViewModelProvider.Factory

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.CreationExtras
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory

class MyViewModel(
    private val myRepository: MyRepository,
) : ViewModel() {
    // ViewModel logic

    // Define ViewModel factory in a companion object
    companion object {

        // Define a custom key using the factory function
        val MY_REPOSITORY_KEY = CreationExtras.Key<MyRepository>()

        val Factory: ViewModelProvider.Factory = viewModelFactory {
            initializer {
                // Get the dependency in your factory
                val myRepository = this[MY_REPOSITORY_KEY] as MyRepository
                MyViewModel(
                    myRepository = myRepository,
                )
            }
        }
    }
}

คุณสามารถสร้างอินสแตนซ์ ViewModel ด้วย CreationExtras.Key ได้โดยตรงใน Composables

import androidx.lifecycle.viewmodel.MutableCreationExtras
import androidx.lifecycle.viewmodel.compose.viewModel
// ...
@Composable
fun MyApp(myRepository: MyRepository) {
    val extras = MutableCreationExtras().apply {
        set(MyViewModel.MY_REPOSITORY_KEY, myRepository)
    }
    val viewModel: MyViewModel = viewModel(
        factory = MyViewModel.Factory,
        extras = extras,
    )
}

แหล่งข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมเกี่ยวกับ ViewModel และทรัพยากร Dependency ได้ที่แหล่งข้อมูลเพิ่มเติมต่อไปนี้

เอกสารประกอบ

ดูเนื้อหา