Android è stato introdotto nel mondo nel 2005 e durante questi 12 anni di esistenza la piattaforma ha raggiunto un successo incredibile, diventando il sistema operativo mobile più installato. In quel periodo, sono state lanciate 14 diverse versioni del sistema operativo, con Android sempre più maturo. Tuttavia, un'area molto importante della piattaforma ha continuato a essere ignorata: un modello di architettura standard, in grado di gestire le peculiarità della piattaforma e abbastanza semplice da essere compreso e adottato dallo sviluppatore medio.
Beh, meglio tardi che mai. All'ultimo Google I / O, il team Android ha finalmente deciso di risolvere questo problema e rispondere al feedback degli sviluppatori di tutto il mondo, annunciando una raccomandazione ufficiale per un'architettura di applicazioni Android e fornendo gli elementi costitutivi per implementarla: la nuova architettura componenti. E ancora meglio, sono riusciti a farlo senza compromettere l'apertura del sistema che tutti conosciamo e amiamo.
In questo tutorial, esploreremo l'architettura standardizzata proposta dal team di Android su Google I / O e analizzeremo gli elementi principali dei nuovi componenti di architettura: Ciclo vitale
, ViewModel
, LifeData
, e Camera
. Non presteremo troppa attenzione al codice, concentrandoci invece sul concetto e la logica dietro questi temi. Daremo anche un'occhiata ad alcuni semplici frammenti, tutti scritti usando Kotlin, un linguaggio sorprendente che ora è ufficialmente supportato da Android.
Se stai appena iniziando il tuo viaggio come sviluppatore, è possibile che tu non sappia esattamente di cosa sto parlando. Dopotutto, l'architettura delle applicazioni può essere un tema oscuro all'inizio. Ma credimi, imparerai presto la sua importanza! Man mano che un'applicazione cresce e diventa più complessa, la sua architettura diventerà sempre più importante. Può letteralmente rendere il tuo lavoro una beatitudine o un inferno vivente.
Mettendola all'incirca, l'architettura di un'applicazione è un piano coerente che deve essere fatto prima dell'avvio del processo di sviluppo. Questo piano fornisce una mappa di come le diverse componenti dell'applicazione devono essere organizzate e legate insieme. Presenta linee guida che dovrebbero essere seguite durante il processo di sviluppo e costringe alcuni sacrifici (generalmente correlati a più classi e boilerplate) che alla fine ti aiuteranno a costruire un'applicazione ben scritta che sia più testabile, espandibile e mantenibile.
L'architettura dell'applicazione software è il processo di definizione di una soluzione strutturata che soddisfa tutti i requisiti tecnici e operativi, ottimizzando al contempo attributi di qualità comuni come prestazioni, sicurezza e gestibilità. Comporta una serie di decisioni basate su una vasta gamma di fattori e ciascuna di queste decisioni può avere un impatto considerevole sulla qualità, le prestazioni, la manutenibilità e il successo complessivo dell'applicazione.
- Microsoft Software Architecture e Design Guide
Una buona architettura prende in considerazione molti fattori, in particolare le caratteristiche e i limiti del sistema. Ci sono molte soluzioni architettoniche diverse là fuori, tutte con pro e contro. Tuttavia, alcuni concetti chiave sono comuni tra tutte le visioni.
Fino all'ultimo Google I / O, il sistema Android non consigliava alcuna architettura specifica per lo sviluppo di applicazioni. Ciò significa che sei completamente libero di adottare qualsiasi modello: MVP, MVC, MVPP o addirittura nessun modello. Inoltre, il framework Android non forniva nemmeno soluzioni native per i problemi creati dal sistema stesso, in particolare dal ciclo di vita del componente.
Quindi, se si desidera adottare un modello Model View Presenter sulla propria applicazione, è necessario elaborare da zero la propria soluzione, scrivere molto codice boilerplate o adottare una libreria senza supporto ufficiale. E quell'assenza di standard ha creato molte applicazioni scritte male, con codebase difficili da mantenere e testare.
Come ho detto, questa situazione è stata criticata per anni. In effetti, di recente ho scritto su questo problema e su come affrontarlo nel mio Come Adottare Model View Presenter su serie Android. Ma la cosa importante è che dopo 12 lunghi anni, il team di Android ha finalmente deciso di ascoltare i nostri reclami e di aiutarci con questo problema.
La nuova Android Architecture Guide definisce alcuni principi chiave a cui una buona applicazione Android dovrebbe conformarsi e propone anche un percorso sicuro affinché lo sviluppatore possa creare una buona app. Tuttavia, la guida afferma esplicitamente che la rotta presentata non è obbligatoria, e in definitiva la decisione è personale; è lo sviluppatore che dovrebbe decidere quale tipo di architettura adottare.
Secondo la guida, una buona applicazione Android dovrebbe fornire una solida separazione di preoccupazioni e guidare l'interfaccia utente da un modello. Qualsiasi codice che non gestisca un'interfaccia utente o un'interazione del sistema operativo non dovrebbe trovarsi in un'attività o in un frammento, poiché mantenerli il più puliti possibile consentirà di evitare molti problemi relativi al ciclo di vita. Dopotutto, il sistema può distruggere attività o frammenti in qualsiasi momento. Inoltre, i dati devono essere gestiti da modelli isolati dall'interfaccia utente e, di conseguenza, dai problemi del ciclo di vita.
L'architettura consigliata da Android non può essere facilmente etichettata tra i modelli standard che conosciamo. Sembra un modello Model View Controller, ma è così strettamente legato all'architettura del sistema che è difficile etichettare ogni elemento usando le convenzioni conosciute. Questo non è rilevante, tuttavia, poiché l'importante è che si affidi ai nuovi componenti di architettura per creare una separazione delle preoccupazioni, con un'eccellente testabilità e manutenibilità. E ancora meglio, è facile da implementare.
Per capire che cosa sta proponendo il team di Android, dobbiamo conoscere tutti gli elementi dei componenti di architettura, dal momento che sono quelli che faranno il grande lavoro per noi. Ci sono quattro componenti, ciascuno con un ruolo specifico: Camera
, ViewModel
, LiveData
, e Ciclo vitale
. Tutte queste parti hanno le proprie responsabilità e lavorano insieme per creare un'architettura solida. Diamo un'occhiata a un diagramma semplificato dell'architettura proposta per capirlo meglio.
Come puoi vedere, abbiamo tre elementi principali, ciascuno con la sua responsabilità.
Attività
e Frammento
rappresentare il vista
livello, che non affronta la logica aziendale e le operazioni complesse. Configura solo la vista, gestisce l'interazione dell'utente e, cosa più importante, osserva ed espone LiveData
elementi presi dal ViewModel
.ViewModel
osserva automaticamente il Ciclo vitale
stato della vista, mantenendo la coerenza durante le modifiche di configurazione e altri eventi del ciclo di vita di Android. È anche richiesto dalla vista di recuperare i dati dal deposito
, che è fornito come osservabile LiveData
. È importante capire che il ViewModel
mai riferimenti al vista
direttamente e che gli aggiornamenti sui dati sono sempre eseguiti da LiveData
entità.deposito
non è un componente Android speciale. È una classe semplice, senza alcuna implementazione particolare, che è responsabile del recupero dei dati da tutte le fonti disponibili, da un database a servizi web. Gestisce tutti questi dati, generalmente li trasforma in osservabili LiveData
e rendendoli disponibili al ViewModel
.Camera
database è una libreria di mapping SQLite che facilita il processo di gestione di un database. Scrive automaticamente una tonnellata di standard, controlla gli errori in fase di compilazione e, soprattutto, può restituire direttamente le query con osservabili LiveData
.Sono sicuro che hai notato che abbiamo parlato molto di osservabili. The Observer Pattern è una delle basi del LiveData
elemento e Ciclo vitale
componenti consapevoli. Questo modello consente a un oggetto di notificare un elenco di osservatori su eventuali modifiche al suo stato o ai dati. Quindi, quando un'attività osserva a LiveData
entità, riceverà aggiornamenti quando tali dati subiscono qualsiasi tipo di modifica.
Un altro consiglio di Android è quello di consolidare la sua architettura utilizzando un sistema di Dependency Injection, come Dagger 2 di Google o utilizzando il pattern Locator di servizio (che è molto più semplice di DI, ma senza molti dei suoi vantaggi). In questo tutorial non tratteremo di DI o Service Locator, ma Envato Tuts + ha alcuni tutorial eccellenti su questi temi. Tuttavia, tieni presente che ci sono alcune particolarità di lavorare con Dagger 2 e componenti Android che verranno spiegati nella seconda parte di questa serie.
Dobbiamo immergerci profondamente negli aspetti delle nuove componenti per essere in grado di comprendere e adottare davvero questo modello di architettura. Tuttavia, non entreremo in tutti i dettagli in questo tutorial. A causa della complessità di ciascun elemento, in questo tutorial parleremo solo dell'idea generale alla base di ognuno di essi e analizzeremo alcuni frammenti di codice semplificati. Cercheremo di coprire abbastanza terreno per presentare i componenti e iniziare. Ma non temere, perché i futuri articoli di questa serie scaveranno in profondità e copriranno tutte le particolarità dei componenti di architettura.
La maggior parte dei componenti delle app Android ha dei cicli di vita collegati, gestiti direttamente dal sistema stesso. Fino a poco tempo fa spettava allo sviluppatore monitorare lo stato dei componenti e agire di conseguenza, inizializzando e terminando le attività al momento opportuno. Tuttavia, è stato davvero facile confondersi e commettere errori legati a questo tipo di operazione. Ma il android.arch.lifecycle
il pacchetto ha cambiato tutto questo.
Ora, Attività e Frammenti hanno a Ciclo vitale
oggetto a loro allegato che può essere osservato da LifecycleObserver
classi, come a ViewModel
o qualsiasi oggetto che implementa questa interfaccia. Ciò significa che l'osservatore riceverà aggiornamenti sui cambiamenti di stato dell'oggetto che sta osservando, come quando un'attività è in pausa o quando sta avviando. Può anche controllare lo stato corrente dell'oggetto osservato. Quindi ora è molto più semplice gestire le operazioni che devono considerare i cicli di vita del framework.
Per ora, per creare un Attività
o Frammento
che è conforme a questo nuovo standard, devi estendere a LifecycleActivity
o LifecycleFragment
. Tuttavia, è possibile che questo non sia sempre necessario, dal momento che il team di Android mira a integrare completamente questi nuovi strumenti con il suo framework.
class MainActivity: LifecycleActivity () override fun onCreate (savedInstanceState: Bundle?) super.onCreate (savedInstanceState) setContentView (R.layout.activity_main)
Il LifecycleObserver
riceve Ciclo vitale
eventi e può reagire attraverso l'annotazione. Non è necessario alcun override del metodo.
class MainActivityObserver: LifecycleObserver, AnkoLogger @OnLifecycleEvent (Lifecycle.Event.ON_RESUME) fun onResume () info ("onResume") @OnLifecycleEvent (Lifecycle.Event.ON_PAUSE) fun onPause () info ("onPause")
LiveData
ComponenteIl LiveData
componente è un titolare di dati che contiene un valore che può essere osservato. Dato che l'osservatore ha fornito un Ciclo vitale
durante LiveData
instantiation, LiveData
si comporterà secondo Ciclo vitale
stato. Se l'osservatore è Ciclo vitale
stato è INIZIATO
o RIPRESO
, l'osservatore è attivo
; altrimenti, lo è non attivo
.
LiveData
sa quando i dati sono stati modificati e anche se l'osservatore è attivo
e dovrebbe ricevere un aggiornamento. Un'altra caratteristica interessante del LiveData
è che è in grado di rimuovere l'osservatore se è in a Lifecycle.State.DESTROYED
stato, evitando perdite di memoria quando osservato da attività e frammenti.
UN LiveData
deve implementare onActive
e onInactive
metodi.
class LocationLiveData (context: Context): LiveData(), AnkoLogger, LocationListener private val locationManager: LocationManager = context.getSystemService (Context.LOCATION_SERVICE) come LocationManager sovrascrive fun onActive () info ("onActive") locationManager.requestLocationUpdates (LocationManager.GPS_PROVIDER, 0, 0f, this) override fun onInactive () info ("onInactive") locationManager.removeUpdates (this) // ...
Per osservare a LiveData
componente, è necessario chiamare osservatore (LifecycleOwner, Observer
.
class MainActivity: LifecycleActivity (), AnkoLogger fun observLocation () val location = LocationLiveData (this) location.observe (this, Observer location -> info ("location: $ location"))
ViewModel
ComponenteUna delle classi più importanti dei nuovi componenti di architettura è il ViewModel
, che è progettato per contenere dati relativi all'interfaccia utente, mantenendo la sua integrità durante le modifiche alla configurazione come le rotazioni dello schermo. Il ViewModel
è in grado di parlare con il deposito
, ottenere LiveData
da esso e rendendolo disponibile a sua volta per essere osservato dalla vista. ViewModel
inoltre non sarà necessario effettuare nuove chiamate al deposito
dopo le modifiche alla configurazione, che ottimizzano molto il codice.
Per creare un modello di vista, estendere il ViewModel
classe.
class MainActivityViewModel: ViewModel () private var notes: MutableLiveData>? = null fun getNotes (): LiveData
> if (notes == null) notes = MutableLiveData
> () loadNotes () note di ritorno !! private fun loadNotes () // esegue un'operazione asincrona per recuperare le note
Per accedere da una vista, è possibile chiamare ViewProviders.of (Attività | frammento) .get (ViewModel :: classe)
. Questo metodo factory restituirà una nuova istanza di ViewModel
o ottenere quello ritenuto, a seconda dei casi.
class MainActivity: LifecycleActivity (), AnkoLogger override fun onCreate (savedInstanceState: Bundle?) super.onCreate (savedInstanceState) setContentView (R.layout.activity_main) val viewModel = ViewModelProviders.of (this) .get (MainActivityViewModel :: class. java) viewModel.getNotes (). observ (this, Observer notes -> info ("note: $ notes"))
Camera
ComponenteAndroid ha supportato SQLite dall'inizio; tuttavia, per farlo funzionare, è sempre stato necessario scrivere molto standard. Inoltre, SQLite non ha salvato POJO (semplici oggetti Java) e non ha controllato le query in fase di compilazione. Arriva Camera
per risolvere questi problemi! È una libreria di mapping SQLite, capace di persistere POJO Java, convertire direttamente le query in oggetti, controllare gli errori in fase di compilazione e produrre LiveData
osservabili dai risultati dell'interrogazione. Camera
è una libreria di mappatura relazionale degli oggetti con alcuni fantastici accessori Android.
Fino ad ora, potevi fare la maggior parte di cosa Camera
è in grado di utilizzare altre librerie Android ORM. Tuttavia, nessuno di essi è ufficialmente supportato e, cosa più importante, non può produrre LifeData
risultati. Il Camera
libreria si adatta perfettamente come il livello persistente sull'architettura Android proposta.
Per creare un Camera
database, avrete bisogno di un @Entità
per persistere, che può essere qualsiasi POJO Java, a @Dao
interfaccia per effettuare query e operazioni di input / output e a @Banca dati
classe astratta che deve estendersi RoomDatabase
.
@Entity class Nota @PrimaryKey var id: Long? = null var text: String? = null var date: Long? = null
@Dao NoteDAO @Insert (onConflict = OnConflictStrategy.REPLACE) fun insertNote (nota: Nota): Long @Update (onConflict = OnConflictStrategy.REPLACE) fun updateNote (nota: Nota): Int @Delete fun deleteNote (nota: Nota) : Int @Query ("SELECT * FROM note") fun findAllNotes (): LiveData// su Kotlin gli argomenti della query vengono rinominati // in arg [N], essendo N il numero dell'argomento. // su Java gli argomenti assumono il suo nome originale @Query ("SELECT * FROM note WHERE id =: arg0") fun findNoteById (id: Long): LiveData
@Database (entities = arrayOf (Note :: class), version = 1) abstract class Databse: RoomDatabase () abstract fun noteDAO (): NoteDAO
Per ora, per utilizzare i nuovi componenti di architettura, devi prima aggiungere il repository di Google al tuo build.gradle
file. Per maggiori dettagli, consultare la guida ufficiale.
allprojects repositories jcenter () // Aggiungi repository Google maven url 'https://maven.google.com'
Come puoi vedere, l'architettura standardizzata proposta da Android coinvolge molti concetti. Non aspettarti di avere ancora una comprensione completa di questo argomento. Dopotutto, stiamo semplicemente introducendo il tema. Ma certamente hai già abbastanza conoscenze per capire la logica dietro l'architettura e i ruoli dei diversi componenti di architettura.
Abbiamo parlato della maggior parte degli argomenti relativi all'architettura Android proposta e ai suoi componenti; tuttavia, dettagli sull'implementazione dei componenti e alcuni extra, come il deposito
classe e il sistema Dagger 2 non possono essere coperti da questa prima parte. Esploreremo questi temi nei prossimi post.
A presto!