Android MVVM UI control

Viewed 804

I'm started to learn MVVM with LiveData on Android. I think displaying and updating basic data is clear to me. The topic I struggle to find a best practice for is controling the UI.

Let's say I have a basic UI, a form for example. It has a few EditTextViews to input data. At the end it also has a switch. If it is ON a few more EditTextViews are shown to fill in. When it's OFF of course they are gone.

My question is where to implement this logic?

  1. In the Activity/Fragment code? Then business logic would be involved in the VIEW part of MVVM (which I don't find great).

  2. In the ViewModel? Then business logic would exist in a, let's say, data cache. This way I would have to create a bunch of boolean getters in the ViewModel which compute the values for separate View visibilities. Then in my Activity in the subscription block for LiveData change I need to read all of these values and set visibility for the views one-by-one.

  3. In a separate Service/Helper/Util class? It would be the same solution as #2 just the logic extracted from the ViewModel.

What is the best practice here? Same question can come up with the topic of user input validation though (and I guess there are a number of these areas).

1 Answers

I'd go with the 2nd approach, but slightly different implenetation (using DataBinding), inspired by Google's sample Sunflower app: https://github.com/android/sunflower It's supposed to be introducing Jetpack best practices, including MVVM.

Then in my Activity in the subscription block for LiveData change I need to read all of these values and set visibility for the views one-by-one.

Instead of doing that you can subscribe your layout to the viewmodel (with DataBinding), similar to this:
https://github.com/android/sunflower/blob/master/app/src/main/res/layout/fragment_plant_detail.xml

    <data>
        <import type="com.google.samples.apps.sunflower.data.Plant"/>
        <variable
            name="viewModel"
            type="com.google.samples.apps.sunflower.viewmodels.PlantDetailViewModel" />
    </data>

and then use set the visibility based on the references to the viewmodel without getters, in the layout itself

app:isGone="@{!viewModel.isUnderAge}"

or

android:visibility="@{viewModel.isUnderAge?  View.VISIBLE : View.INVISIBLE}"
Related