Tạo ViewModel có các phần phụ thuộc   Một phần của Android Jetpack.

Làm theo các phương pháp hay nhất về chèn phần phụ thuộc, ViewModel có thể lấy các phần phụ thuộc làm tham số trong hàm khởi tạo. Đây chủ yếu là các loại từ lớp miền hoặc lớp dữ liệu. Vì khung cung cấp ViewModel, nên bạn cần có một cơ chế đặc biệt để tạo các thực thể của khung đó. Cơ chế đó là giao diện ViewModelProvider.Factory. Chỉ các cách triển khai giao diện này mới có thể tạo bản sao các ViewModel trong phạm vi phù hợp.

ViewModel với CreationExtras

Nếu một lớp ViewModel nhận phần phụ thuộc trong hàm khởi tạo của lớp đó, hãy cung cấp nhà máy triển khai giao diện ViewModelProvider.Factory. Ghi đè hàm create(Class<T>, CreationExtras) để cung cấp bản sao mới của ViewModel.

CreationExtras cho phép bạn truy cập thông tin liên quan giúp tạo thực thể cho ViewModel. Dưới đây là danh sách các khoá có thể truy cập từ lớp bổ sung:

Khoá Chức năng
ViewModelProvider.NewInstanceFactory.VIEW_MODEL_KEY Cấp quyền truy cập vào khoá tuỳ chỉnh mà bạn đã truyền đến ViewModelProvider.get().
ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY Cung cấp quyền truy cập vào thực thể của lớp Application.
SavedStateHandleSupport.DEFAULT_ARGS_KEY Cấp quyền truy cập vào Gói đối số mà bạn nên sử dụng để tạo SavedStateHandle.
SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY Cấp quyền truy cập vào SavedStateRegistryOwner đang được dùng để tạo ViewModel.
SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY Cấp quyền truy cập vào ViewModelStoreOwner đang được dùng để tạo ViewModel.

Để tạo thực thể mới của SavedStateHandle, hãy sử dụng hàm CreationExtras.createSavedStateHandle() và truyền thực thể đó đến ViewModel.

CreationExtras với APPLICATION_KEY

Sau đây là ví dụ về cách cung cấp một thực thể của ViewModel mà lấy một kho lưu trữ thuộc phạm vi lớp ApplicationSavedStateHandle làm phần phụ thuộc:

    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
                    )
                }
            }
        }
    }

Sau đó, bạn có thể sử dụng nhà máy này khi truy xuất một phiên bản của ViewModel:

import androidx.lifecycle.viewmodel.compose.viewModel

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

Truyền tham số tuỳ chỉnh dưới dạng CreationExtras

Bạn có thể truyền các phần phụ thuộc đến ViewModel thông qua CreationExtras bằng cách tạo khoá tuỳ chỉnh. Điều này có thể hữu ích nếu ViewModel của bạn phụ thuộc vào các đối tượng không thể truy cập thông qua lớp ApplicationAPPLICATION_KEY. Ví dụ về trường hợp này là khi ViewModel được tạo bên trong mô-đun Kotlin Multiplatform và do đó không có quyền truy cập vào các phần phụ thuộc của Android.

Trong ví dụ này, ViewModel xác định một khoá tuỳ chỉnh và sử dụng khoá đó trong 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,
                )
            }
        }
    }
}

Bạn có thể tạo thực thể cho ViewModel bằng CreationExtras.Key trực tiếp trong các thành phần kết hợp.

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,
    )
}

Tài nguyên khác

Để tìm hiểu thêm về ViewModel và các phần phụ thuộc, hãy xem thêm các tài nguyên sau:

Tài liệu

Nội dung về Lượt xem