Home > front end >  How the MVVM ViewModel DataBinding shoud look like for NavigationView
How the MVVM ViewModel DataBinding shoud look like for NavigationView

Time:02-05

I did not find any example showing this. I am very beginning to MVVM DataBinding and ViewModel.

I want to perform an action once the element in NavigationView in DrawerLayout is clicked. Without any design pattern I would do this in very easy way but this MVVM is very hard pattern.

I was thinking about MutableLiveData in ViewModelMain and then observing it in ActivityMain but I have no idea what to observe in this example.

Here is my code:

ActivityMain.java

(...)

@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
    int id = item.getItemId();
    if(id == R.id.nav_account) {
        Toast.makeText(this, "abc", Toast.LENGTH_SHORT).show();
        drawerLayout.close();
    }
    return false;
}

ViewModelMain.java

public class ViewModelMain extends ViewModel {

}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 
xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@ id/my_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout

        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <FrameLayout
            android:id="@ id/content_frame"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toTopOf="@ id/bottom_navigation"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <com.google.android.material.bottomnavigation.BottomNavigationView
            android:id="@ id/bottom_navigation"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:background="?attr/colorBottomNavigationViewBg"
            app:itemHorizontalTranslationEnabled="true"
            app:itemTextColor="?attr/colorBottomNavigationViewItem"
            app:layout_constraintBottom_toBottomOf="parent"
            app:menu="@menu/menu_bottom_navigation" />

    </RelativeLayout>

    <com.google.android.material.navigation.NavigationView
        android:id="@ id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/menu_navigation_drawer"
        app:itemIconTint="?colorDayNight" />


</androidx.drawerlayout.widget.DrawerLayout>

CodePudding user response:

Firstly I would like to point out that there is a difference between DataBinding and ViewBinding. DataBinding allows you to bind UI components in your layouts (in the XML) to data sources in your app. I am a bit biased against DataBinding. I don't like and don't use it.

ViewBinding is a way to bind your view elements in your app code and remove the constant need of writing findViewById. It generates a binding class for each XML layout that you can use in your activities/fragments(views).

In your case you will be fine just with view binding. Here are the android docs: https://developer.android.com/topic/libraries/view-binding

Next it depends what action you want to perform. Let's imagine you want to display how many times the element has been clicked.

Your ViewModel will be responsible for handling that logic, while your view for observing and displaying the changes. (I will try to write this in java, but I haven't used Java in a long time, you should also consider switching to Kotlin)

public class ViewModelMain extends ViewModel {
    private MutableLiveData<Integer> _timesClicked = new MutableLiveData<>();
    
    public void increaseClickCounter() {
        int currentTimesClicked = _timesClicked.getValue();
        _timesClicked.setValue(  currentTimesClicked);
    }

    public LiveData<Integer> getTimesClicked() {
        if (_timesClicked == null) {
            _timesClicked = new MutableLiveData<>();
            _timesClicked.setValue(0);
        }

        return _timesClicked;
    }

}

To read about viewbinding in your activity you can go here: https://developer.android.com/topic/libraries/view-binding#activities

You now need to add viewBinding and viewModle to your activity. This will become part of your activity's code:

private ActivityMainBinding binding; //notice the "Binding" suffix at the end

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
        
    viewModel = new ViewModelProvider(this).get(ViewModelMain.class);

    binding = ActivityMainBinding.inflate(getLayoutInflater());
    View view = binding.getRoot();
    setContentView(view);

    initClickListeners();
    startObservingData();

}

private void initClickListeners() {
    ///replace "yourButton" with an element from your XML. 
    binding.yourButton.setOnClickListener(new View.OnClickListener() {
        viewModel.increaseClickCounter();
    });
}

private void startObservingData() {
    viewModel.getTimesClicked().observe(this, timesClicked -> {
        Toast.makeText(this, timesClicked.intValue(), Toast.LENGTH_SHORT).show();
    });

}

  •  Tags:  
  • Related