Goal and Sandwiches

Mauro Pisanu
6 min readSep 22, 2021

--

È la mia primissima app, perchè da qualche parte si deve pure iniziare.

Con questo articolo voglio dimostrarvi come sono riuscito a mettere in piedi un’app che registri i punteggi di due giocatori di E-Football ‘21.
È così che ha avuto inizio il mio percorso formativo in OverApp.

Progettazione UI

Schema dell’interfaccia grafica

Per iniziare ho creato una bozza grafica di quello che avevo in mente per l’interfaccia:
una serie di righe orizzontali, con uno o più elementi, di cui segue una breve spiegazione.

Le prime due immagini, hanno il ruolo di rappresentare i giocatori tra i quali avverrà la sfida; troviamo poi i nomi degli sfidanti; mentre scendendo nella terza riga ecco il numero di vittorie, posto rispettivamente sotto ogni player, con al centro i pareggi. A seguire vediamo i comandi dell’app, dove i bottoni posti ai due estremi in alto servono per aumentare il punteggio dell’uno e dell’altro giocatore. I bottoni agli estremi inferiori a diminuirlo. Il tutto mentre al centro è ben chiaro il risultato della partita corrente. Troviamo ancora il bottone di salvataggio, grazie al quale si può salvare il risultato parziale e incrementare il numero di vittorie o pareggi. Poco più in basso, invece, è presente il bottone destinato a resettare gli score salvati. Per concludere sono presenti i risultati di ogni partita salvata con le rispettive date.

Costruzione dell’applicazione step-by-step

Al fine di mostrare tutti i componenti e il ruolo che questi hanno nell’applicazione mostrerò la costruzione dell’applicazione passaggio dopo passaggio.

Il codice sorgente mostrato, però, è quello presente nell’applicazione finale.

Ho definito l’architettura dell’applicazione usando un pattern MVVM (Model-View-ViewModel). È presente dunque una Main Activity che funge da controller, alla quale sono legati l’interfaccia grafica ed un View Model che gestisce ogni dato con la sua logica applicativa.

Fase sviluppo prima parte

Ho impostato inizialmente gli eventi click-listener all’interno della main activity, in modo che la pressione sui bottoni faccia si che venga modificato il punteggio parziale. Cliccando sul bottone di salvataggio invece si aumentando il numero di pareggi e/o di vittorie.

Permanenza del dato

Il passo successivo è stato quello di rendere permanente ogni score affinché fosse possibile proseguire con il conteggio delle vittorie e dei pareggi negli utilizzi futuri dell’applicazione.

È stato indispensabile l’utilizzo di un database. Ho optato per la tecnologia RealmDb in modo da rendere permanenti gli score di ogni partita, cosicché da questi si potesse risalire anche al numero di partite vinte e/o pareggiate.

Come prima cosa ho creato una classe ScoreDbItem che estenda la classe Realm Object, usata per interfacciarsi con il database stesso.

Tale classe è qui rappresentata:

Una volta creata la classe ScoreDbItem ho creato una classe singleton DatabaseManager che funga da wrapper nei confronti del database.

La presenza di un Database Manager, che offra dei metodi per interfacciarsi con il database, fa si che, nel caso si debba cambiare la tecnolgia che utilizza il database, dovrà essere cambiato solamente il codice del Database Manager stesso.

Per inizializzare il database ho esteso la classe Application.

Tale estensione è il punto di ingresso del programma, dove é presente l’unica istanza del database.

A quel punto il programma era in grado di immagazzinare permanentemente il risultato di ciascuna partita e da tali risultati era possibile anche ottenere il numero di vittorie e di pareggi.

Utilizzo Recycler View

Da quel momento il programma aveva una sua struttura elementare che permetteva il parziale funzionamento. Ecco quindi che sono andato a modificare l’interfaccia grafica e ad aggiungere elementi a livello logico.

Per mostrare la lista con il punteggio di ogni partita ho utilizzato una Recycler View in cui, però, poi ho inserito anche gli elementi grafici che rendono funzionante l’applicazione.

Segmentando l’interfaccia grafica nella maniera più granulare possibile, sono riuscito ad ottenere di ogni parte una view.

È stata questa scelta a rendere possibile un futuro cambio di posizione degli elementi, tenendo conto della possibilità di aggiungerne o rimuoverne.

Per far si che la Recycler View venisse popolata ho utilizzato quindi una classe che trasforma i dati in viste.

La classe da estendere per svolgere questo ruolo è stata quindi la RecyclerView.Adapter.

Come riportato nel gist precedente ho definito sette View Type.
Ai primi sei sono stati associati i View Holder contenenti le views con i vari elementi dell’interfaccia grafica, che rendono l’applicazione utilizzabile. Al settimo invece è attribuito il View Holder contenente la view che mostra il risultato di ogni partita.

Con il metodo onBindViewHolder ho fatto sì che ogni vista mostri i relativi dati necessari.

Dopo aver implementato nella maniera corretta l’override dei metodi della classe Adapter ho quindi la possibilità di poter vedere le varie viste all’interno della Recycler View.

Listener

A questo punto ho dovuto implementare i button listener all’interno dell’Adapter. Per far si che alla pressione dei bottoni situati all’interno della Recycler View venissero modificati i dati all’interno del View Model, ho creato un listener che avrebbe propagato gli eventi dell’Adapter al Main Activity in cui è presente l’istanza del View Model.

Nel riquadro sottostante possiamo vedere la porzione di codice dell’interfaccia:

Qui invece è visibile l’override dei metodi che saranno usati all’interno dell’adapter:

Infinity Scroll

Il passaggio successivo è stato quello di evitare di caricare tutti gli score del database nello stesso momento, caricandone solamente cinque alla volta.

Il caricamento sarebbe dovuto avvenire nel momento in cui arrivati al limite della lista si fosse effettuato lo scroll.

Per far ciò è stato necessario catturare l’evento di scrolling.

Ho esteso dunque la classe RecycleView.OnScrollListener prendendo spunto da del codice trovato in rete:

L’istanza della classe mostrata è stata inserita come parametro nel metodo setOnLoadMoreListener della Recycler View

A questo punto nel View Model è stata creata una lista in cui vengono aggiunti gradualmente gli elementi del database.

Per non mostrare due volte lo stesso score, ho dovuto far si che gli elementi già presenti nella lista non fossero ricaricati dal database.

Per far ciò carico dal database i cinque elementi precedenti a quello con indice [Lunghezza.elementi.database — lunghezza.elementi.lista] e li aggiungo alla lista.

Gli elementi della lista verranno riordinati in base alla data, prima di essere dati in pasto all’Adapter. Resterà la necessità di aggiornare la UI ogni qualvolta si carichino dei nuovi dati sul database.

Per far questo ho creato un listener che propaga gli eventi dal Database Manager al Main Activity che a sua volta si serve dell’Adapter per aggiornare la UI.

Qui è mostrata l’interfaccia :

A seguire invece, viene mostrato l’override del metodo che sarà usato all’interno del view Model:

L’applicazione può finalmente funzionare.

NB: Ogni gist riporta il codice dell’app.

Ringrazio Laura per avermi aiutato nella stesura dell’articolo e Davide ed Elia per i preziosi consigli.

--

--