1

I'm a beginner with Android development, and I'm trying to make a practice app using MVVM. It's my first experience with this architecture, so I'm pretty unsure of everything that I do so far.

I'm trying to programmatically set the CollapsingToolBar's scroll flags. When the RecyclerView's list is empty, I'd like to disable the scrolling effect. When it has items, I reenable it.

In my ViewModel, I have:

@HiltViewModel
class MealsViewModel @Inject constructor(
    private val mealDao : MealDao
) : ViewModel() {

    \\ depending on the calendar day, grab the list of meals from the Room Database
    private val currentDay: MutableLiveData<Date> = MutableLiveData(Date())
    val meals = Transformations.switchMap(currentDay){ date -> mealDao.getMeals(date).asLiveData() }

    \\ this is observed in the fragment; if meals is empty from database, return this int (scroll flag)
    val enableOrDisableScroll = meals.map {
        if (it.isNullOrEmpty()) AppBarLayout.LayoutParams.SCROLL_FLAG_NO_SCROLL else
                    AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP or
                            AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL or
                                AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED
    }

In the Fragment, enableOrDisableScroll is observed like so:

            viewModel.enableOrDisableScroll.observe(viewLifecycleOwner) {
                val params: AppBarLayout.LayoutParams = collapsingToolBar.layoutParams
                        as AppBarLayout.LayoutParams

                \\ it is the returned value from the ViewModel observation
                params.scrollFlags = it
                collapsingToolBar.layoutParams = params
            }

(This solution is modified from https://stackoverflow.com/a/32699543/11813571)

Is this proper MVVM design? Is all the "business logic" properly separated from the view (Fragment)? I may be having trouble understanding the term itself. In Android programming, is business logic anything that would decide how a view is created and UI updated? How could my MVVM approach be improved? It works as intended, but I don't know if it's optimal.

Thank you!

cjames
  • 65
  • 1
  • 9
  • You should not have instances of `View` in `ViewModel`. `ViewModel` is just a place to store the logic related to data and what data is displayed to the UI through `LiveData`, or `StateFlow`. Remember that. – Dương Minh Aug 22 '21 at 06:58
  • And I think you should read app architecture recommended by Google. [Guild app architecture](https://developer.android.com/jetpack/guide) – Dương Minh Aug 22 '21 at 07:00
  • @DươngMinh, I was using the AppBarLayout View class for its constants (the SCROLL_FLAGs). I didn't instantiate or reference a View directly from within the ViewModel. Is that permissible? If not, would making another class and injecting it as a helper be a good work around? – cjames Aug 22 '21 at 09:20

1 Answers1

3

enter image description here

This is how Basically MVVM pattern looks like .It is quite simple , the View (Fragment , Activity , Custom Views ) should only communicate with the ViewModel , it shouldn't call any other classes . The ViewModel acts as a middle-men for your data and the views . So the data should be passed from your datasource (which looking at your code seems to be room database ) to the viewModel and from there to the View .For passing the data from ViewModel to the views, one should make use of LiveData /StateFlow /SharedFLow . Now , the data in the viewModel should not come directly from DataSource if you want to follow MVVM strictly . There has to be another layer called Repository between your datasource and viewModel as shown in the diagram . In your code , in ViewModel you have directly called datasource in the form of (dao) , that is not permissible . The repository acts as a middle-men for data to flow between the datasource and the ViewModel . This is how MVVM works .

Answers to your Questions :

1.Is this proper MVVM design : The ViewModel -Fragment logic has been handled well but you have directly called dao in your viewModel which is faulty . You have to create a Repository , where you have to call Dao and have to pass that repository in the ViewModel .

  1. What is business logic ? The answer will partly be a matter of the project's complexity and of developer's taste . But make sure that it does not have any View related code in it and it should flow via ViewModel . The business logic should be reusable and should be kept away from other classes
Karunesh Palekar
  • 2,190
  • 1
  • 9
  • 18