Make writing a habit together! This is the 14th day of my participation in the “Gold Digging Day New Plan · April More Text Challenge”. Click here for more details.

This article focuses on the basic techniques for using the ViewModel

1. The ViewModel constructor supports passing Application

AndroidViewModel; AndroidViewModel; AndroidViewModel;

class ApplicationViewModel(app: Application) : AndroidViewModel(app) {
    / / get Applicaction
    private val mApp: Application by lazy {
        getApplication()
    }
}
Copy the code

We can then get the Application using the getApplication() method.

2. The ViewModel constructor supports passing in other types of arguments

ViewModel support was introduced into the Factory class to create a specific type of ViewModel, so we inherit ViewModelProvider directly. The Factory custom a Factory class, and at the time of creating the ViewModel Factory class in the custom.

For example, we support the MainViewModel constructor to pass in an Int:

class CustomVMFactory(
    private val factory: ViewModelProvider.Factory,
    private val type: Int
) : ViewModelProvider.Factory {
    override fun 
        create(modelClass: Class<T>): T {
        if (modelClass.isAssignableFrom(MainViewModel::class.java)) {
            return MainViewModel(type) as T
        }
        return factory.create(modelClass)
    }
}
Copy the code

As you can see, our custom CustomVMFactory factory class also has to pass in a default Activity factory to ensure that if our custom factory class fails to create a ViewModel, it will be passed to the original Activity default factory. Essentially, this is an implementation of the static proxy pattern.

Use as follows:

private val mVM by viewModels<MainViewModel> {
    CustomVMFactory(
        defaultViewModelProviderFactory,
        5)}Copy the code

3. Note on the use of LiveData in ViewModel

Normally we define LiveData in ViewModel like this:

// Private mutable
private val data: MutableLiveData<Response<String>> = MutableLiveData()
// External leakage is immutable
val data1: LiveData<Response<String>> get() = data
Copy the code

Our exposed immutable data1 essentially declares an additional member variable and a member method:

By decomcompiling the code, the extra declared attributes are not necessary at all, just the getData1 method to get the immutable LiveData.

So we can transform it like this:

// External leakage is immutable
val data1: LiveData<String> get() =  MutableLiveData()
Copy the code

Decompile to see the effect:

As you can see from the decomcompiled code, exposing immutable LiveData only declares one extra method, reducing the declaration of one extra property.

4. Use of coroutines in ViewModel

Rely on implementation “androidx lifecycle: lifecycle – viewmodel – KTX: $lifecycle_version” provides the viewmodel collaborators in range extended attributes: viewModelScope

We can use the viewModelScope property directly to perform time-consuming operations and thread switches:

fun request(a) {
    viewModelScope.launch(Dispatchers.IO) {
        // Execute time-consuming code, such as network requests}}Copy the code