Introducere în componentele de arhitectură Android

Android a fost introdus în lume în 2005, iar în cei 12 ani de existență platforma a obținut un succes uluitor, devenind cel mai instalat sistem de operare mobil. În acel moment, au fost lansate 14 versiuni diferite ale sistemului de operare, Android devenind tot mai matur. Cu toate acestea, o zonă foarte importantă a platformei a continuat să fie ignorată: un model de arhitectură standard capabil să manipuleze particularitățile platformei și suficient de simplu pentru a fi înțeles și adoptat de dezvoltatorul mediu.

Ei bine, mai târziu decât niciodată. La ultimul Google I / O, echipa Android a decis în cele din urmă să soluționeze această problemă și să răspundă la feedback-ul de la dezvoltatori din întreaga lume, anunțând o recomandare oficială pentru o aplicație Android Architecture și oferind blocurile necesare implementării acesteia: noua arhitectură Componente. Și mai bine, au reușit să o facă fără a compromite deschiderea sistemului pe care îl cunoaștem și îl iubim cu toții.

În acest tutorial, vom explora arhitectura standardizată propusă de echipa Android de la Google I / O și vom analiza elementele principale ale noilor componente ale arhitecturii: Ciclu de viață, ViewModel, LifeData, și Cameră. Nu vom acorda prea multă atenție codului, concentrându-ne în schimb asupra conceptului și logicii din spatele acestor teme. Vom analiza, de asemenea, câteva fragmente simple, toate scrise cu ajutorul lui Kotlin, un limbaj uimitor, care este acum oficial susținut de Android.

1. Ce a fost lipsit de Android?

Dacă începeți călătoria în calitate de dezvoltator, este posibil să nu știți exact despre ce vorbesc. La urma urmei, arhitectura aplicațiilor poate fi o temă obscură la început. Dar crede-mă, vei învăța cât de curând este importanța ei! Pe măsură ce o aplicație crește și devine mai complexă, arhitectura acesteia va deveni din ce în ce mai importantă. Se poate face literalmente munca ta o fericire sau un iad viu.

Arhitectura aplicațiilor

Aplicând-o aproximativ, o arhitectură a aplicațiilor este un plan consistent care trebuie făcut înainte de începerea procesului de dezvoltare. Acest plan oferă o hartă a modului în care diferitele componente ale aplicației ar trebui să fie organizate și legate împreună. Prezintă linii directoare care trebuie urmate în timpul procesului de dezvoltare și forțează unele sacrificii (în general legate de mai multe clase și boilerplate), care în final vă vor ajuta să construiți o aplicație bine scrisă, mai testabilă, mai extensibilă și mai durabilă.

Arhitectura aplicațiilor software este procesul de definire a unei soluții structurate care să îndeplinească toate cerințele tehnice și operaționale, în timp ce optimizează atributele de calitate comune, cum ar fi performanța, securitatea și gestionarea. Aceasta implică o serie de decizii bazate pe o gamă largă de factori și fiecare dintre aceste decizii poate avea un impact considerabil asupra calității, performanței, mentenabilității și succesului general al aplicației.
- Ghidul de arhitectură și design al software-ului Microsoft

Arhitectura bună ia în considerare mai mulți factori, în special caracteristicile și limitele sistemului. Există multe soluții arhitecturale diferite, toate cu argumente pro și contra. Cu toate acestea, unele concepte-cheie sunt comune între toate viziunile.

Vechile greșeli

Până la ultima intrare / ieșire Google, sistemul Android nu a recomandat nici o arhitectură specifică pentru dezvoltarea aplicațiilor. Aceasta înseamnă că ați fost complet liber să adoptați orice model acolo: MVP, MVC, MVPP, sau chiar nici un model deloc. În plus, cadrul Android nu oferă chiar soluții native pentru problemele create de sistemul în sine, în special ciclul de viață al componentei.

Deci, dacă ați dori să adoptați modelul modelului View Viewer pe aplicația dvs., trebuie să veniți cu soluția proprie de la zero, să scrieți o mulțime de coduri de bare sau să adoptați o bibliotecă fără sprijin oficial. Iar această lipsă de standarde a creat o mulțime de aplicații prost scrise, cu coduri de bază care au fost greu de întreținut și de testat. 

Așa cum am spus, această situație a fost criticată de ani de zile. De fapt, am scris recent despre această problemă și cum să o abordez în modul meu de a adopta modelul View Viewer pe seria Android. Dar cel mai important este că după 12 ani lungi, echipa Android a decis în cele din urmă să ne asculte plângerile și să ne ajute cu această problemă.

2. Arhitectura Android

Noul Ghid de arhitectură Android definește câteva principii-cheie pe care trebuie să le respecte o aplicație Android bună și propune, de asemenea, o cale sigură dezvoltatorului pentru a crea o aplicație bună. Cu toate acestea, ghidul afirmă explicit că ruta prezentată nu este obligatorie și, în cele din urmă, decizia este personală; dezvoltatorul ar trebui să decidă ce tip de arhitectură să adopte.

Conform ghidului, o bună aplicație Android ar trebui să ofere o separare solidă a preocupărilor și să conducă UI-ul de la un model. Orice cod care nu se ocupă de interfața UI sau de interacțiunea sistemului de operare nu ar trebui să fie într-o activitate sau un fragment, deoarece păstrarea acestora cât mai curată va permite să evitați multe probleme legate de ciclul de viață. La urma urmei, sistemul poate distruge Activități sau Fragmente în orice moment. De asemenea, datele ar trebui să fie tratate de modele izolate de interfața utilizator și, prin urmare, de problemele ciclului de viață.

Noua arhitectură recomandată

Arhitectura pe care o recomandă Android nu poate fi ușor de etichetat printre modelele standard pe care le cunoaștem. Seamănă cu un model model de vizualizare a modelului, dar este atât de strâns legat de arhitectura sistemului încât e greu să etichetați fiecare element folosind convențiile cunoscute. Acest lucru nu este relevant, totuși, deoarece lucrul important este că se bazează pe noile componente ale arhitecturii pentru a crea o separare a preocupărilor, cu testabilitate și mentenabilitate excelente. Și mai bine, este ușor de implementat.

Pentru a înțelege ceea ce propune echipa Android, trebuie să cunoaștem toate elementele Componentelor de Arhitectură, deoarece acestea sunt cele care vor face ridicarea greutăților pentru noi. Există patru componente, fiecare având un rol specific: Cameră, ViewModel, LiveData, și Ciclu de viață. Toate aceste părți au responsabilități proprii și lucrează împreună pentru a crea o arhitectură solidă. Să aruncăm o privire asupra unei diagrame simplificate a arhitecturii propuse pentru ao înțelege mai bine.

După cum puteți vedea, avem trei elemente principale, fiecare cu responsabilitatea sa. 

  1. Activitate și Fragment reprezintă Vedere strat, care nu se ocupă de logica de afaceri și operațiunile complexe. Acesta configurează doar vizualizarea, gestionează interacțiunea cu utilizatorul și, cel mai important, observă și expune LiveData elemente preluate din ViewModel.
  2. ViewModel monitorizează automat Ciclu de viață starea opiniei, menținerea consecvenței în timpul schimbărilor de configurație și a altor evenimente pe durata ciclului de viață Android. Este, de asemenea, solicitat de punctul de vedere pentru a prelua date de la Repertoriu, care este furnizat ca observabil LiveData. Este important să înțelegeți că ViewModel nu trimite referințe la Vedere direct și că actualizările privind datele sunt întotdeauna efectuate de către LiveData entitate.
  3. Repertoriu nu este o componentă specială Android. Este o clasă simplă, fără o implementare specială, care este responsabilă pentru preluarea datelor din toate sursele disponibile, de la o bază de date la servicii web. Acesta gestionează toate aceste date, transformându-le, în general, în observabile LiveData și punerea la dispoziția acestora ViewModel.
  4. Cameră baza de date este o bibliotecă de mapare SQLite care facilitează procesul de abordare a unei baze de date. Se scrie automat o tona de boilerplate, verifică erorile la timpul de compilare și, cel mai bine, se poate întoarce în mod direct interogările cu observabile LiveData.

Sunt sigur că ați observat că am vorbit mult despre observații. Modelul de observator este una dintre bazele LiveData element și Ciclu de viață constienti. Acest model permite unui obiect să notifice o listă de observatori cu privire la orice modificare a stării sale sau a datelor. Deci, atunci când o activitate observă a LiveData entitate, acesta va primi actualizări atunci când aceste date vor suferi modificări.

O altă recomandare Android este să-și consolideze arhitectura folosind un sistem Dependency Injection, cum ar fi Google Dagger 2 sau folosind modelul Locator de servicii (care este mult mai simplu decât DI, dar fără multe avantaje). Nu vom acoperi DA sau Service Locator în acest tutorial, dar Envato Tuts + are câteva tutoriale excelente despre aceste teme. Cu toate acestea, fiți atenți la faptul că există anumite particularități de lucru cu Dagger 2 și Android Components, care vor fi explicate în a doua parte a acestei serii.

3. Componente de arhitectură

Trebuie să ne aruncăm adânc în aspectele noilor componente pentru a înțelege și adopta cu adevărat acest model de arhitectură. Cu toate acestea, nu vom intra în toate detaliile din acest tutorial. Datorită complexității fiecărui element, în acest tutorial, vom vorbi doar despre ideea generală din spatele fiecăruia și vom examina câteva fragmente de cod simplificate. Vom încerca să acoperim terenul suficient pentru a prezenta componentele și pentru a începe. Dar frica nu, pentru că articolele viitoare din această serie vor sapa adânc și vor acoperi toate particularitățile componentelor arhitecturii.

Componentele bazate pe ciclul de viață

Majoritatea componentelor aplicației Android au cicluri de viață atașate acestora, care sunt gestionate direct de sistemul în sine. Până de curând, dezvoltatorul a fost obligat să monitorizeze starea componentelor și să acționeze în consecință, inițializând și terminând sarcinile la momentul potrivit. Cu toate acestea, a fost foarte ușor să vă confundați și să faceți greșeli legate de acest tip de operațiune. Cu exceptia android.arch.lifecycle pachetul a schimbat toate acestea. 

Acum, activitățile și fragmentele au a Ciclu de viață obiect atașat la ele, care poate fi observat de către LifecycleObserver clase, cum ar fi ViewModel sau orice obiect care implementează această interfață. Aceasta înseamnă că observatorul va primi actualizări despre modificările de stare ale obiectului pe care îl observă, cum ar fi atunci când o Activitate este întreruptă sau când începe. De asemenea, poate verifica starea curentă a obiectului observat. Deci, acum este mult mai ușor să gestionăm operațiunile care trebuie să ia în considerare ciclurile de viață cadru.

Pentru moment, pentru a crea un Activitate sau Fragment care se conformează acestui nou standard, trebuie să extindeți a LifecycleActivity sau LifecycleFragment. Cu toate acestea, este posibil ca acest lucru să nu fie întotdeauna necesar, deoarece echipa Android vizează integrarea completă a acestor instrumente noi cu cadrul său.

class MainActivity: LifecycleActivity () suprascrie fun onCreate (savedInstanceState: Bundle?) super.onCreate (savedInstanceState) setContentView (R.layout.activity_main)

LifecycleObserver primește Ciclu de viață evenimente și poate reacționa prin adnotare. Nu este necesară nicio suprascriere a metodei.

class MainActivityObserver: LifecycleObserver, AnkoLogger @OnLifecycleEvent (Lifecycle.Event.ON_RESUME) distracție onResume () info ("onResume") @OnLifecycleEvent (Lifecycle.Event.ON_PAUSE) fun onPause

LiveData component

LiveData componenta este un suport de date care conține o valoare care poate fi observată. Având în vedere faptul că observatorul a furnizat o Ciclu de viață in timpul LiveData instanțierea, LiveData se va comporta în funcție de Ciclu de viață stat. În cazul în care observatorul este  Ciclu de viață de stat este ÎNCEPUT sau reluate, observatorul este activ; altfel, este inactiv

LiveData știe când au fost schimbate datele și, de asemenea, dacă observatorul este activ și ar trebui să primească o actualizare. O altă caracteristică interesantă a LiveData este că este capabil să înlăture observatorul dacă este în a Lifecycle.State.DESTROYED stat, evitând scurgeri de memorie când sunt observate de către Activități și Fragmente.

A LiveData trebuie să pună în aplicare onActive și onInactive metode.

clasa LocationLiveData (context: Context): LiveData(), AnkoLogger, LocationListener privat val locationManager: LocationManager = context.getSystemService (Context.LOCATION_SERVICE) ca LocationManager suprascrie distracția onActive () info ("onActive") locationManager.requestLocationUpdates (LocationManager.GPS_PROVIDER, 0, 0f, this) înlocuiți distracția onInactive () info ("onInactive") locationManager.removeUpdates (this) // ...

Pentru a observa a LiveData componente, trebuie să sunați observator (LifecycleOwner, Observer).

Clasa principală: LifecycleActivity (), AnkoLogger fun observeLocation () val location = LocationLiveData (this) location.observe (this, Observer location -> info

ViewModel component

Una dintre cele mai importante clase ale noilor componente de arhitectură este ViewModel, care este proiectat să dețină date care sunt legate de interfața de utilizare, menținându-și integritatea în timpul schimbărilor de configurație, cum ar fi rotațiile ecranului. ViewModel este capabil să discute cu Repertoriu, obtinerea LiveData de la el și de a face disponibil la rândul său, să fie respectate de vedere. ViewModel de asemenea, nu va trebui să facă apeluri noi către Repertoriu după modificările configurației, care optimizează foarte mult codul.

Pentru a crea un model de vizualizare, extindeți ViewModel clasă.

class MainActivityViewModel: ViewModel () note private var: MutableLiveData>? = null distracție getNotes (): LiveData> if (note == null) notes = MutableLiveData> () loadNotes () note de întoarcere !!  încărcare privată distractivăNotes () // efectuați operația async pentru a prelua notele

Pentru a accesa dintr-o vizualizare, puteți apela ViewProviders.of (Activitate | Fragment) .get (ViewModel :: clasa). Această metodă din fabrică va returna o nouă instanță a metodei ViewModel sau obțineți cel reținut, după caz. 

class MainActivity: LifecycleActivity (), AnkoLogger suprascrie fun onCreate (savedInstanceState: Bundle?) super.onCreate (savedInstanceState) setContentView (R.layout.activity_main) val viewModel = ViewModelProviders.of (this) .get (MainActivityViewModel :: class. java) viewModel.getNotes () observați (acest lucru, Observatorul notes -> info ("note: $ notes"))

Cameră component

Android acceptă SQLite de la început; cu toate acestea, pentru a face să funcționeze, a fost întotdeauna necesar să scrie o mulțime de boilerplate. De asemenea, SQLite nu a salvat POJOs (obiecte Java obișnuite) și nu a verificat interogările la momentul compilării. Împreună vine Cameră pentru a rezolva aceste probleme! Este o bibliotecă de mapare SQLite, capabilă să persiste Java POJOs, transformând direct interogările în obiecte, verificând erorile la timpul de compilare și producând LiveData observabile din rezultatele interogării. Cameră este o bibliotecă Object Relational Mapping cu câteva extra-cool Android.

Până acum puteai să faci cea mai mare parte din ceea ce făceai Cameră este capabil să utilizeze alte biblioteci ORM Android. Cu toate acestea, niciuna dintre ele nu este susținută oficial și, cel mai important, nu poate produce LifeData rezultate. Cameră biblioteca se potrivește perfect ca stratul persistent pe arhitectura Android.

Pentru a crea un Cameră baza de date, veți avea nevoie de un @Entitate pentru a persista, care poate fi orice POJO Java, a @Dao interfață pentru a face interogări și operații de intrare / ieșire și a @Bază de date clasa abstractă care trebuie extinsă RoomDatabase.

@ Notă de clasă Entity @PrimaryKey var id: Long? = null var text: String? = null var data: Long? = null
@ Interfață Dda NoteDAO @Insert (onConflict = OnConflictStrategy.REPLACE) distracție insertNote (notă: Notă): Long @Update (onConflict = OnConflictStrategy.Revision) fun updateNote (notă: Notă: Int @Delete fun deleteNote : Int @Query ("SELECT * FROM notă") fun findAllNotes (): LiveData // pe Kotlin argumentele interogării sunt redenumite // to arg [N], fiind N numărul argumentului. // pe Java argumentele își asumă numele original @Query ("SELECT * FROM note WHERE id =: arg0") distracție findNoteById (id: Long): LiveData 
@Database (entități = arrayOf (Notă :: clasă), versiune = 1) clasă abstractă Databse: RoomDatabase () abstract note noteDAO (): NoteDAO

Adăugarea componentelor de arhitectură la proiectul dvs.

Pentru moment, pentru a utiliza noile componente de arhitectură, va trebui mai întâi să adăugați depozitul Google la dvs. build.gradle fişier. Pentru mai multe detalii, consultați ghidul oficial.

allprojects repositories jcenter () // Adăugați Google repository maven url 'https://maven.google.com'

Concluzie

După cum puteți vedea, arhitectura standardizată propusă de Android implică o mulțime de concepte. Nu vă așteptați să înțelegeți complet acest subiect. La urma urmei, noi doar introducem tema. Dar cu siguranță aveți suficientă cunoștință până acum pentru a înțelege logica din spatele arhitecturii și rolurile diferitelor componente ale arhitecturii.

Am vorbit despre majoritatea temelor legate de arhitectura Android și componentele sale; cu toate acestea, detalii despre implementarea componentelor și câteva extras, cum ar fi Repertoriu clasa și sistemul Dagger 2 nu pot fi acoperite de această primă parte. Vom explora aceste teme în următoarele postări.

Ne vedem în curând!

Cod