preface

I wrote two articles about the ViewModel about six months ago (but I recommend reading the official documentation) :

Official document: ViewModel

The official document: the ViewModel address: developer.android.com/topic/libra…

My previous article: A little bit into the Pit JetPack: ViewModel article

Saved State Module for ViewModel

The official document: Saved State module for the ViewModel address: developer.android.com/topic/libra…

My previous article: Limitations of ViewModel, destruction of rebuild scheme SavedStateHandle

The article written before now is also no problem, ViewModel should talk about the basic also talked about. So today’s post is more of a supplement to the previous one:

  • Why the ViewModel exists
  • Android-KTX enhancements to ViewModel
  • Incorrect use of ViewModel

The body of the

The official definition of a ViewModel is:

  • 1. Class responsibilities: Responsible for preparing data for the interface (meaning all business code that handles the data logic should be written in the ViewModel)
  • 2. ViewModel objects are automatically retained during configuration changes: thus can be used as a cornerstone for cross-fragment communication

Let’s dig a little deeper into these two definitions:

First, the meaning of ViewModel

In the Model/View/ViewModel(MVVM) Model, the ViewModel layer is defined like this:

The above Model/View/ViewModel(MVVM) Model link address: docs.microsoft.com/zh-cn/archi…

Only a small number of View layer controls can be directly data-bound to the Model layer, especially if the Model layer is out of the developer’s control (provided by someone else). The data provided by the Model layer is probably not directly mapped to the controls. In addition, UI controls may need to perform complex operations that don’t make sense to write in the View layer (because they don’t belong in UI control logic), and that operation logic is too specific to be included in the Model layer (because that’s not what the Model layer should care about). So, we need a place to handle View layer state.

The ViewModel layer is responsible for these tasks. The ViewModel layer contains the data converters that convert the Model layer data structures to the View layer data structures, and contains commands that the View layer can use to interact with the Model layer.

From the above definition, it is clear that the ViewModel layer is the transformation layer. It is used to convert the output data of the Model layer into the input data used by the View layer, and convert the output data of the View layer into the input data used by the Model layer.

We’ll see that the definition of ViewModel in MVVM is very similar to the first responsibility definition of the ViewModel library released by Google.

Therefore, it is natural to use ViewModel as an implementation of the ViewModel layer in MVVM. Now that we use the ViewModel as the ViewModel layer, one of its main purposes is clear: to organize our code and tell us that the code that processes the data should be written in the ViewModel.

With the first intent clear, let’s look at the second intent above: save ViewModel instances during configuration updates.

In just a few words, there are two important messages:

  • 1. The ViewModel instance’s lifetime is long for activities/fragments.
  • The ViewModel can’t handle the Activity destroying and rebuilding.

The first message means we can’t do this:

If you need a context, you can use AndroidViewModel

What about the second information? See the limitations of the ViewModel to destroy the reconstructed scheme SavedStateHandle

Second, the Android – KTX

To explain what KTX is:

Android KTX is a set of Kotlin extensions included in Android Jetpack and other Android libraries.

The KTX extension provides concise idiomatic Kotlin code for Jetpack, the Android platform, and other apis. To this end, these extensions take advantage of a variety of Kotlin language features, including:

  • Extension function
  • Extended attributes
  • Lambda
  • Named parameters
  • Parameter Default Value
  • coroutines

There are a lot of KTX. If you are interested in learning about other KTX content, you can visit the official website.

The website address: developer. The android. Google. Cn/kotlin/KTX?…

2.1. What does Fragment-KTX offer us?

When we get a ViewModel instance, it looks something like this:

lateinit var viewModel: XXViewModel

override fun onCreate(savedInstanceState: Bundle?). {
    super.onCreate(savedInstanceState)
    viewModel = ViewModelProviders.of(this)[XXViewModel::class.java]
}
Copy the code

To use the SavedStateHandle, do this:

lateinit var viewModel: XXViewModel

override fun onCreate(savedInstanceState: Bundle?). {
    super.onCreate(savedInstanceState)
    viewModel = ViewModelProvider(
        this,
        SavedStateViewModelFactory(Application, this)
    )[XXViewModel::class.java]
}
Copy the code

Big trouble, and this is all sample code. If we introduce fragment-ktx:

dependencies {
    implementation "Androidx. Fragments: fragments - KTX: 1."
}
Copy the code

The above two methods of initializing the ViewModel can be simplified to a single by keyword:

// Fragment level ViewModel
private val viewModel: XXViewModel by viewModels()
// Activity-level ViewModel
private val viewModel: XXViewModel by activityViewModels()
Copy the code

2.2. What does viewModel-KTX offer us?

We are provided with a coroutine environment, viewModelScope, so in the ViewModel, if we want to use coroutines, we can just:

viewModelScope.launch  {
    // ...
}
Copy the code

And you don’t have to worry about whether the Job is cancelled.

Note that coroutines are collaborative. Instead of calling job.canel (), we need to determine whether the current coroutine is alive based on isActive displayed in the corresponding launch (the coroutine part will have a chance to expand again).

Incorrect use of ViewModel

After that, let’s talk about mistakes or mistakes.

3.1. Proceed cautiously with R.string.xxx in AndroidViewModel

Let’s start with the following code:

public class MyViewModel extends AndroidViewModel {
    public final MutableLiveData<String> statusLabel = new MutableLiveData<>();
    
    public SampleViewModel(Application context) {
        super(context); statusLabel.setValue(context.getString(R.string.labelString)); }}Copy the code

The problem with this usage is that the ViewModel does not destroy the rebuild when the configuration is updated, so the constructor does not go back.

Therefore, if r.string.labelString needs to be replaced dynamically at this time, it is not correct in this case.

So loading a string dynamically in a ViewModel is a bit tricky, so be careful.

3.2 ViewModel cannot solve the destruction and reconstruction problem

Destruction and reconstruction, this problem probably no one attention, but once encountered this problem is basically “fatal”.

The destruction of rebuilding address: developer.android.com/topic/libra…

When “certain” is not null, there is a null pointer crash. This kind of case is attributed to destruction and reconstruction basically cannot escape.

The scenario for the recreate destroy rebuild is simple. In the Developer options, turn on: Do not keep the activity.

Therefore, member variables, callbacks, and so on are stored in the ViewModel. It’s dangerous in a destruction and reconstruction scenario. So what do you do about that?

  • Member variables (can be ignored if the business scenario does not care to destroy and rebuild. If you can’t ignore it, look back at the opening article.)
  • Callback (In the next LiveData article, a reasonable solution to handle Callback will be developed based on Google’s article)

The end of the

So much for the ViewModel.

The above content is mainly launched from the perspective of two architectures and “pits”. More than that, I want to output an idea (I hope all students can accept it). First, I want to think about the significance of the emergence of technology from the official documents. With this foundation to see other web articles, you can take its essence to its dregs.

I am a fresh graduate, recently and friends maintain a public account, the content is that we in the transition from fresh graduate to the development of this way stepped on the pit, as well as our step by step learning records, if interested in friends can pay attention to it, together with fuel ~