Search code examples
javaandroiduser-interfacemvvmandroidx

Simple MVVM architecture on Android with AndroidX on Java



I'm getting really annoyed trying to figure out how the frick creates a simple MVVM pattern Android activity.

What I want is simply bind a view model public method (which prints a "Eureka!" log), to a Button (with onClick action).


To achieve this, what I did since now is:

data_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="it.XXXXX.XXXXX.ui.data.DataActivity"
    >

    <data>
        <variable
            name="viewModel"
            type="it.XXXXX.XXXXX.ui.data.DataViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:id="@+id/some_useless_id_1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal"
                android:textAppearance="@style/TextAppearance.AppCompat.Body1"
                tools:text="Press this beautiful button ;)" />

            <Button
                android:id="@+id/some_useless_id_2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="@{() -> viewModel.test()}"
                android:text="@string/button" />
        </LinearLayout>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

DataViewModel.java

package it.XXXXX.XXXXX.ui.data;

import android.util.Log;

import androidx.lifecycle.ViewModel;

public class DataViewModel extends ViewModel {
    public void test() {
        Log.d("test", "EUREKA!");
    }
}

DataActivity.java

package it.XXXXX.XXXXX.ui.data;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;

import android.os.Bundle;

import it.XXXXX.XXXXX.R;

public class DataActivity extends AppCompatActivity {

    private DataViewModel mViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.data_activity);
        this.mViewModel = new ViewModelProvider(this).get(DataViewModel.class);
    }
}

...finally (since I'm working on an existent application) I call the View with:

...
        ((Button)this.findViewById(R.id.btnDataSync2)).setOnClickListener(new OnClickListener(){
            public void onClick(View arg0) {
                Intent i = new Intent(MainActivity.this, DataActivity.class);
                MainActivity.this.startActivity(i);
            }
        });
...

The expected behavior is to read a log by pressing on the DataView (which is loaded), but nothing happens (except the button press animation).

Does anyone have any idea what the problem might be?
Thank you in advance!


Solution

  • I figure that I was not binding correctly the ViewModel from the Activity:


    DataActivity.java

    public class DataActivity extends AppCompatActivity {
    
        private DataViewModel mViewModel;
        private DataActivityBinding mBinding;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            this.mViewModel = new DataViewModel();
            this.mBinding = DataBindingUtil.setContentView(this, R.layout.data_activity);
            this.mBinding.setViewModel(this.mViewModel);
        }
    }
    



    hope this will help someone.



    Ps. thanks @medaip90 for the useful advice!