MVVM e ViewModel in Android con Java: Guida Completa

A clean technical illustration showing the MVVM architecture pattern for Android development with Java. Shows three layers: Model, View, and ViewModel connected with arrows, with Android logo and Java code snippets in the background. Modern flat design style with blue and green colors.

MVVM e ViewModel in Android con Java: guida completa

MVVM (Model-View-ViewModel) è uno dei pattern architetturali più usati nello sviluppo Android moderno. Separando in modo chiaro logica di presentazione, interfaccia utente e gestione dei dati, aiuta a creare app più pulite, testabili e facili da mantenere. In questa guida vediamo come usare MVVM e la classe ViewModel in Android con Java, passo dopo passo.

MVVM ViewModel Android Java - schema architettura

Introduzione a MVVM (Model-View-ViewModel)

MVVM è un pattern che organizza il codice in tre parti principali. Ogni parte ha responsabilità ben precise e comunica con le altre in modo strutturato, riducendo al minimo i collegamenti diretti tra interfaccia grafica e sorgenti dati.

  • Model: rappresenta i dati e la logica di business. Include entità, sorgenti dati locali o remote e repository.
  • View: è l’interfaccia utente, cioè Activity, Fragment e layout XML. Mostra i dati e inoltra le azioni dell’utente.
  • ViewModel: contiene la logica di presentazione. Espone dati osservabili alla View (ad esempio tramite LiveData) e coordina l’accesso al Model.

In MVVM la View osserva il ViewModel, che a sua volta usa il Model per recuperare e aggiornare i dati. Questo flusso rende il codice più modulare e semplifica sia i test sia l’evoluzione del progetto nel tempo.

Cos’è il ViewModel in Android

Il classe ViewModel è una classe fornita dalla libreria AndroidX (pacchetto androidx.lifecycle) progettata per gestire e conservare i dati necessari alla UI. La caratteristica principale è che il ViewModel sopravvive ai cambi di configurazione, come la rotazione dello schermo.

Ogni ViewModel è collegato al ciclo di vita di una Activity o di un Fragment. Finché il relativo componente non viene definitivamente distrutto, l’istanza di ViewModel rimane la stessa, evitando di perdere lo stato a ogni ricreazione della UI.

Esempio di ViewModel semplice in Java

public class ContatoreViewModel extends ViewModel {

    private final MutableLiveData<Integer> contatore = new MutableLiveData<>();

    public ContatoreViewModel() {
        contatore.setValue(0);
    }

    public LiveData<Integer> getContatore() {
        return contatore;
    }

    public void incrementa() {
        Integer valore = contatore.getValue();
        if (valore == null) {
            valore = 0;
        }
        contatore.setValue(valore + 1);
    }
}

In questo esempio il ViewModel espone un contatore come LiveData e offre un metodo pubblico per incrementarne il valore. La UI si limiterà a osservare il LiveData e a chiamare incrementa() quando necessario.

Dipendenze ViewModel e LiveData per Android Java (build.gradle)

Per usare ViewModel e LiveData in un progetto Android con Java è necessario aggiungere le dipendenze di AndroidX nel file build.gradle del modulo app.

dependencies {
    // Lifecycle ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel:2.8.0"

    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata:2.8.0"

    // Facoltativo: estensioni per il testing
    testImplementation "androidx.arch.core:core-testing:2.2.0"
}

Le versioni possono cambiare nel tempo, quindi è consigliabile verificare sempre la documentazione ufficiale per usare le release più recenti e compatibili con il proprio progetto.

Creare un ViewModel in Java

Per creare un ViewModel in Java è sufficiente estendere la classe ViewModel o, se servono l’application context o componenti legati ad esso, la classe AndroidViewModel. All’interno del ViewModel si definiscono i LiveData che rappresentano lo stato della UI e i metodi per aggiornarli.

public class UtenteViewModel extends ViewModel {

    private final MutableLiveData<String> nomeUtente = new MutableLiveData<>();

    public LiveData<String> getNomeUtente() {
        return nomeUtente;
    }

    public void caricaUtente() {
        // Qui potresti chiamare un Repository per recuperare i dati
        nomeUtente.setValue("Mario Rossi");
    }
}

Il ViewModel non deve avere riferimenti diretti a Activity, Fragment o View. In questo modo rimane indipendente dal framework Android e può essere testato più facilmente.

Collegare il ViewModel Android all’Activity in Java

Per ottenere un’istanza di ViewModel da una Activity si usa normalmente la classe ViewModelProvider. Il provider si occupa di creare il ViewModel la prima volta e di restituire poi sempre la stessa istanza finché l’Activity è in vita.

public class MainActivity extends AppCompatActivity {

    private UtenteViewModel utenteViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        utenteViewModel = new ViewModelProvider(this)
                .get(UtenteViewModel.class);

        // Da qui in poi puoi usare utenteViewModel
    }
}

Se invece vuoi condividere lo stesso ViewModel tra più Fragment all’interno della stessa Activity, puoi usare il metodo new ViewModelProvider(requireActivity()) direttamente nel Fragment.

LiveData e ViewModel in Android Java

LiveData è una classe osservabile consapevole del ciclo di vita. Quando i dati cambiano, notifica automaticamente solo gli observer che si trovano in uno stato attivo (STARTED o RESUMED), evitando aggiornamenti inutili o potenziali crash.

Osservare un LiveData dal ViewModel Android

public class MainActivity extends AppCompatActivity {

    private UtenteViewModel utenteViewModel;
    private TextView textViewNome;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textViewNome = findViewById(R.id.text_nome);

        utenteViewModel = new ViewModelProvider(this)
                .get(UtenteViewModel.class);

        utenteViewModel.getNomeUtente().observe(this, new Observer<String>() {
            @Override
            public void onChanged(String nome) {
                textViewNome.setText(nome);
            }
        });

        utenteViewModel.caricaUtente();
    }
}

Quando il ViewModel aggiorna il LiveData, la Activity riceve automaticamente la notifica e aggiorna la UI senza bisogno di gestire manualmente il ciclo di vita degli observer.

Esempio completo MVVM in Android Java

Vediamo ora un esempio completo e minimale di architettura MVVM in Java, con un ViewModel che gestisce una lista di note in memoria e una Activity che osserva i cambiamenti per aggiornare la UI.

ViewModel per una lista di note

public class NotaViewModel extends ViewModel {

    private final MutableLiveData<List<String>> note = new MutableLiveData<>();

    public NotaViewModel() {
        note.setValue(new ArrayList<String>());
    }

    public LiveData<List<String>> getNote() {
        return note;
    }

    public void aggiungiNota(String testo) {
        List<String> listaCorrente = note.getValue();
        if (listaCorrente == null) {
            listaCorrente = new ArrayList<String>();
        }
        listaCorrente.add(testo);
        note.setValue(listaCorrente);
    }
}

Activity che osserva il ViewModel in Java

public class MainActivity extends AppCompatActivity {

    private NotaViewModel notaViewModel;
    private TextView textViewNote;
    private Button buttonAggiungi;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textViewNote = findViewById(R.id.text_note);
        buttonAggiungi = findViewById(R.id.button_aggiungi);

        notaViewModel = new ViewModelProvider(this)
                .get(NotaViewModel.class);

        notaViewModel.getNote().observe(this, new Observer<List<String>>() {
            @Override
            public void onChanged(List<String> note) {
                StringBuilder builder = new StringBuilder();
                for (String n : note) {
                    builder.append("- ").append(n).append("\n");
                }
                textViewNote.setText(builder.toString());
            }
        });

        buttonAggiungi.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                notaViewModel.aggiungiNota("Nuova nota");
            }
        });
    }
}

Questo esempio non usa un database, ma dimostra chiaramente il flusso MVVM: la View notifica l’azione al ViewModel, il ViewModel aggiorna i dati, e la View reagisce ai cambiamenti osservando il LiveData.

Vantaggi di MVVM

Adottare MVVM con ViewModel e LiveData porta diversi benefici pratici nello sviluppo di app Android in Java.

  • Separazione chiara delle responsabilità: la UI non conosce i dettagli di persistenza o rete, e il Model non conosce l’interfaccia grafica.
  • Maggiore testabilità: il ViewModel può essere testato con normali test JUnit senza dipendere dal framework Android.
  • Gestione automatica del ciclo di vita: LiveData notifica solo le componenti attive, riducendo il rischio di crash e memory leak.
  • Codice più pulito e leggibile: Activity e Fragment si concentrano sulla UI, mentre il ViewModel gestisce lo stato e la logica di presentazione.
  • Facilità di estensione: introdurre nuove sorgenti dati o nuove schermate risulta più semplice grazie a una struttura già organizzata.

Conclusione: MVVM e ViewModel in Android con Java

In questa guida abbiamo visto come impostare un’architettura MVVM di base in Android con Java, usare ViewModel e LiveData e collegarli ad Activity e Fragment. A partire da questi concetti puoi integrare repository, database locali e chiamate di rete per gestire scenari reali più complessi.

Per approfondire altri aspetti dello sviluppo Android in Java, puoi leggere anche questi articoli correlati:

Commenti

Lascia un commento