Android ble introdusert til verden tilbake i 2005, og i løpet av de 12 års eksistens har plattformen oppnådd utrolig suksess, og ble den mest installerte mobile OS. I løpet av den tiden har 14 forskjellige versjoner av operativsystemet blitt lansert, og Android blir alltid mer moden. Et svært viktig område av plattformen fortsatte imidlertid å bli ignorert: et standard arkitekturmønster, i stand til å håndtere plattformens særegenheter og enkelt nok til å bli forstått og vedtatt av den gjennomsnittlige utvikleren.
Vel, bedre sent enn aldri. På den siste Google I / O-enheten besluttet Android-teamet endelig å løse dette problemet og svare på tilbakemeldingene fra utviklere over hele verden, og annonserte en offisiell anbefaling for en Android Application Architecture og ga byggesteinene å implementere den: den nye arkitekturen komponenter. Og enda bedre, klarte de å gjøre det uten å kompromittere åpenheten til systemet som vi alle kjenner og elsker.
I denne veiledningen vil vi utforske den standardiserte arkitekturen som ble foreslått av Android-teamet på Google I / O, og se på hovedelementene i de nye arkitekturkomponentene: Livssyklus
, ViewModel
, LifeData
, og Rom
. Vi vil ikke betale for mye oppmerksomhet til koden, i stedet fokusere på konseptet og logikken bak disse temaene. Vi vil også ta en titt på noen enkle utdrag, alle skrevet med Kotlin, et fantastisk språk som nå offisielt støttes av Android.
Hvis du bare begynner reisen din som utvikler, er det mulig at du ikke vet nøyaktig hva jeg snakker om. Tross alt kan applikasjonsarkitektur i første omgang være et uklar tema. Men tro meg, du vil lære dens betydning snart nok! Ettersom applikasjonen vokser og blir mer kompleks, blir arkitekturen stadig viktigere. Det kan bokstavelig talt gjøre arbeidet ditt lykke eller et levende helvete.
Å legge det omtrent, en applikasjonsarkitektur er en konsekvent plan som må gjøres før utviklingsprosessen starter. Denne planen gir et kart over hvordan de forskjellige programkomponentene skal organiseres og knyttes sammen. Den presenterer retningslinjer som bør følges i løpet av utviklingsprosessen og styrker noen ofre (generelt relatert til flere klasser og boilerplate) som til slutt vil hjelpe deg å konstruere en velskrevet applikasjon som er mer testbar, utvidbar og vedlikeholdsbar.
Programvarearkitektur er prosessen med å definere en strukturert løsning som oppfyller alle tekniske og operasjonelle krav, samtidig som man optimaliserer vanlige kvalitetsattributter som ytelse, sikkerhet og håndterbarhet. Det innebærer en rekke beslutninger basert på et bredt spekter av faktorer, og hver av disse beslutningene kan ha stor innvirkning på kvaliteten, ytelsen, vedlikeholdbarheten og den generelle suksessen til søknaden.
- Microsofts programvarearkitektur og designguide
God arkitektur tar mange faktorer i betraktning, spesielt systemets egenskaper og grenser. Det er mange forskjellige arkitektoniske løsninger der ute, alle med fordeler og ulemper. Noen nøkkelbegreper er imidlertid felles mellom alle visjoner.
Inntil den siste Google I / O, anbefaler ikke Android-systemet noen spesiell arkitektur for applikasjonsutvikling. Det betyr at du var helt fri til å adoptere en modell der ute: MVP, MVC, MVPP, eller til og med ingen mønster i det hele tatt. I tillegg har Android-rammeverket ikke engang oppnådd opprinnelige løsninger for problemer opprettet av selve systemet, spesielt komponentets livssyklus.
Så, hvis du ønsket å adoptere et modellvisningsmønster på din søknad, måtte du komme med din egen løsning fra bunnen av, skrive mye kjedekode eller vedta et bibliotek uten offisiell støtte. Og det manglende standarder skapte mange dårlig skrevet applikasjoner, med kodebaser som var vanskelig å vedlikeholde og teste.
Som jeg sa, har denne situasjonen blitt kritisert i årevis. Faktisk skrev jeg nylig om dette problemet og hvordan det skal håndteres i Min How To Adopt Model View Presenter på Android-serien. Men det viktigste er at etter 12 lange år besluttet Android-teamet endelig å lytte til våre klager og å hjelpe oss med dette problemet.
Den nye Android Architecture Guide definerer noen sentrale prinsipper som en god Android-applikasjon skal overholde, og foreslår også en sikker måte for utvikleren å lage en god app. Imidlertid er det i retningslinjene uttrykkelig at ruten som presenteres ikke er obligatorisk, og til slutt er avgjørelsen personlig; Det er utvikleren som bør bestemme hvilken type arkitektur å adoptere.
Ifølge guiden bør en god Android-applikasjon gi en solid adskillelse av bekymringer og kjøre brukergrensesnittet fra en modell. Enhver kode som ikke håndterer en brukerinterface eller operativsysteminteraksjon, bør ikke være i en aktivitet eller fragment, fordi du kan unngå mange livssyklusrelaterte problemer fordi du holder dem så rene som mulig. Tross alt, kan systemet ødelegge aktiviteter eller fragmenter når som helst. Også dataene skal håndteres av modeller som er isolert fra brukergrensesnittet, og dermed fra livssyklusproblemer.
Arkitekturen som Android anbefaler, kan ikke lett merkes blant standardmønstrene som vi kjenner. Det ser ut som et modellvisningskontrollmønster, men det er så nært knyttet til systemets arkitektur at det er vanskelig å merke hvert element ved hjelp av de kjente konvensjonene. Dette er imidlertid ikke relevant, da det er viktig at den bygger på de nye arkitekturkomponentene for å skape en adskillelse av bekymringer, med utmerket testbarhet og vedlikeholdsevne. Og enda bedre, det er lett å implementere.
For å forstå hva Android-teamet foreslår, må vi kjenne alle elementene i arkitekturkomponentene, siden de er de som vil gjøre det tungt å løfte for oss. Det er fire komponenter, hver med en bestemt rolle: Rom
, ViewModel
, LiveData
, og Livssyklus
. Alle disse delene har sitt eget ansvar, og de jobber sammen for å skape en solid arkitektur. La oss ta en titt på et forenklet diagram over den foreslåtte arkitekturen for å forstå det bedre.
Som du ser, har vi tre hovedelementer, hver med ansvar.
Aktivitet
og Fragment
representerer Utsikt
lag, som ikke omhandler forretningslogikk og komplekse operasjoner. Den konfigurerer bare visningen, håndterer brukerens samhandling, og viktigst, observerer og utstiller LiveData
elementer tatt fra ViewModel
.ViewModel
observerer automatisk Livssyklus
Status på visningen, opprettholde konsistens under konfigurasjonsendringer og andre Android-livssyklushendelser. Det kreves også av visningen å hente data fra Oppbevaringssted
, som er gitt som observerbar LiveData
. Det er viktig å forstå at ViewModel
aldri refererer til Utsikt
direkte og at oppdateringene på dataene alltid gjøres av LiveData
enhet.Oppbevaringssted
er ikke en spesiell Android-komponent. Det er en enkel klasse, uten noen bestemt implementering, som er ansvarlig for å hente data fra alle tilgjengelige kilder, fra en database til webtjenester. Den håndterer alle disse dataene, vanligvis forvandler dem til observerbare LiveData
og gjøre dem tilgjengelige for ViewModel
.Rom
database er et SQLite kartlegging bibliotek som letter prosessen med å håndtere en database. Den skriver automatisk tonevis av boilerplate, sjekker feil på kompileringstid, og best av alt, kan den direkte returnere spørringer med observerbare LiveData
.Jeg er sikker på at du har lagt merke til at vi har snakket mye om observables. Observermønsteret er et av basene til LiveData
element og Livssyklus
oppmerksomme komponenter. Dette mønsteret gjør det mulig å varsle en liste over observatører om endringer i tilstand eller data. Så når en aktivitet observerer en LiveData
enhet, vil det motta oppdateringer når dataene gjennomgår noen form for endring.
En annen Android-anbefaling er å konsolidere arkitekturen ved hjelp av et Dependency Injection-system, som Googles Dagger 2 eller ved hjelp av Service Locator-mønsteret (som er enklere enn DI, men uten mange av fordelene). Vi vil ikke dekke DI eller Service Locator i denne opplæringen, men Envato Tuts + har noen gode opplæringsprogrammer om disse temaene. Vær imidlertid oppmerksom på at det er noen spesifikasjoner å jobbe med Dagger 2 og Android-komponenter som forklares i den andre delen av denne serien.
Vi må dykke dypt inn i aspektene av de nye komponentene for å kunne virkelig forstå og vedta denne modellen av arkitektur. Imidlertid kommer vi ikke inn i alle detaljene i denne opplæringen. På grunn av kompleksiteten til hvert element, i denne opplæringen, snakker vi bare om den generelle ideen bak hver enkelt og ser på noen forenklede kodestykker. Vi prøver å dekke nok bakken for å presentere komponentene og komme i gang. Men vær ikke redd, fordi fremtidige artikler i denne serien vil grave dypt og dekke alle spesifikasjonene til arkitekturkomponentene.
De fleste av Android app komponentene har livscykler knyttet til dem, som administreres direkte av selve systemet. Inntil nylig var det opp til utvikleren å overvåke komponentens tilstand og handle tilsvarende, initierte og avslutte oppgaver på riktig tidspunkt. Det var imidlertid veldig enkelt å bli forvirret og gjøre feil relatert til denne typen operasjon. Men android.arch.lifecycle
pakken endret alt det.
Nå har aktiviteter og fragmenter a Livssyklus
objekt knyttet til dem som kan observeres av LifecycleObserver
klasser, som a ViewModel
eller ethvert objekt som implementerer dette grensesnittet. Det betyr at observatøren vil motta oppdateringer om tilstandsendringene i objektet som det observerer, som når en aktivitet er pauset eller når den starter. Det kan også sjekke nåværende tilstand for det observerte objektet. Så det er mye lettere å håndtere operasjoner som må vurdere rammens livscykler.
For nå, å opprette en Aktivitet
eller Fragment
som samsvarer med denne nye standarden, må du utvide a LifecycleActivity
eller LifecycleFragment
. Det er imidlertid mulig at dette ikke alltid vil være nødvendig, siden Android-teamet har som mål å integrere disse nye verktøyene helt med rammen.
klasse MainActivity: LifecycleActivity () override fun onCreate (savedInstanceState: Bundle?) super.onCreate (savedInstanceState) setContentView (R.layout.activity_main)
De LifecycleObserver
mottar Livssyklus
hendelser og kan reagere gjennom annotasjon. Ingen metodeoverstyring er nødvendig.
klasse MainActivityObserver: LifecycleObserver, AnkoLogger @OnLifecycleEvent (Lifecycle.Event.ON_RESUME) moro påResume () info ("onResume") @OnLifecycleEvent (Lifecycle.Event.ON_PAUSE) moro påPause () info ("onPause")
LiveData
KomponentDe LiveData
komponent er en dataholder som inneholder en verdi som kan observeres. Gitt at observatøren har gitt a Livssyklus
under LiveData
oppretting, LiveData
vil oppføre seg i henhold til Livssyklus
stat. Hvis observatøren er Livssyklus
staten er GANG
eller gjenopptatt
, Observeren er aktiv
; ellers er det uvirksom
.
LiveData
vet når dataene ble endret og også hvis observatøren er aktiv
og bør motta en oppdatering. En annen interessant egenskap av LiveData
er at den er i stand til å fjerne observatøren hvis den er i a Lifecycle.State.DESTROYED
tilstand, unngå minnelekkasje når observert av aktiviteter og fragmenter.
EN LiveData
må gjennomføre onActive
og onInactive
fremgangsmåter.
klasse LocationLiveData (kontekst: Kontekst): LiveData(), AnkoLogger, LocationListener private val locationManager: LocationManager = context.getSystemService (Context.LOCATION_SERVICE) som LocationManager overstyrer moro onActive () info ("onActive") locationManager.requestLocationUpdates (LocationManager.GPS_PROVIDER, 0, 0f, dette) overstyr moro onInactive () info ("onIctive") locationManager.removeUpdates (this) // ...
Å observere a LiveData
komponent, du må ringe observatør (LifecycleOwner, Observer
.
klasse MainActivity: LifecycleActivity (), AnkoLogger fun observeLocation () val location = LocationLiveData (denne) location.observe (dette Observer sted -> info ("sted: $ location"))
ViewModel
KomponentEn av de viktigste klassene i de nye arkitekturkomponentene er ViewModel
, som er utformet for å holde data som er relatert til brukergrensesnittet, og opprettholder integriteten under konfigurasjonsendringer som skjermrotasjoner. De ViewModel
er i stand til å snakke med Oppbevaringssted
, får LiveData
fra det og gjøre det tilgjengelig i sin tur å bli observert av utsikten. ViewModel
trenger ikke å ringe til Oppbevaringssted
etter konfigurasjonsendringer, som optimaliserer koden mye.
For å opprette en visningsmodell, utvider du ViewModel
klasse.
klasse MainActivityViewModel: ViewModel () private var notater: MutableLiveData>? = null morsomme getNotes (): LiveData
> if (noter == null) notater = MutableLiveData
> () loadNotes () retur notater !! Private Fun LoadNotes () // gjør async-operasjon for å hente notater
For å få tilgang til en visning, kan du ringe ViewProviders.of (Activity | fragment) .Få (ViewModel :: klasse)
. Denne fabrikkmetoden returnerer en ny forekomst av ViewModel
eller få den beholdte, etter behov.
klasse MainActivity: LifecycleActivity (), AnkoLogger overstyr moro onCreate (savedInstanceState: Bundle?) super.onCreate (savedInstanceState) setContentView (R.layout.activity_main) val viewModel = ViewModelProviders.of (dette) .get (MainActivityViewModel :: class. java) viewModel.getNotes (). observere (dette Observer notater -> info ("notater: $ notater"))
Rom
KomponentAndroid støttet SQLite fra starten; Men for å få det til å fungere, var det alltid nødvendig å skrive mye kjeleplate. Dessuten lagret ikke SQLite POJOs (vanlig gamle Java-objekter), og sjekket ikke spørringer på kompileringstidspunktet. Langs kommer Rom
å løse disse problemene! Det er et SQLite kartlegging bibliotek, i stand til å vedvare Java POJOs, direkte konvertere spørringer til objekter, sjekke feil på kompileringstid og produsere LiveData
observerbare resultater fra spørringsresultater. Rom
er et Objekt Relational Mapping-bibliotek med noen kule Android-ekstramateriale.
Inntil nå kan du gjøre det meste av det Rom
kan bruke andre ORM Android-biblioteker. Imidlertid er ingen av dem offisielt støttet, og viktigst av alt, kan de ikke produsere LifeData
resultater. De Rom
biblioteket passer perfekt som det vedvarende laget på den foreslåtte Android arkitekturen.
Å opprette en Rom
database, trenger du en @Entity
å fortsette, noe som kan være noen Java POJO, a @Dao
grensesnitt for å lage spørringer og inn / ut-operasjoner, og a @Database
abstrakt klasse som må utvides RoomDatabase
.
@Entity class Note @PrimaryKey var id: Long? = null var tekst: String? = null var dato: lang? = null
@Dao-grensesnittet NoteDAO @Insert (onConflict = OnConflictStrategy.REPLACE) morsomt settNote (notat: Notat): Lang @Update (onConflict = OnConflictStrategy.REPLACE) morsom oppdateringNote (notat: Notat): Int @Delete Fun delete note : Int @Query ("SELECT * FROM note") morsomt finneAlle notater (): LiveData// på Kotlin blir spørringsargumentene omdøpt // til arg [N], som er N argumentnummeret. // på Java antar argumentene sitt opprinnelige navn @Query ("VELG * FRA notat WHERE id =: arg0") morsomt funnetNoteById (id: Lang): LiveData
@Database (enheter = arrayOf (Note :: klasse), versjon = 1) abstrakt klasse Databse: RoomDatabase () abstrakt morsomt notat (): NoteDAO
For nå, for å bruke de nye arkitekturkomponentene, må du først legge til Google-depotet til din build.gradle
fil. For mer informasjon, se den offisielle veiledningen.
allprojects repositories jcenter () // Legg til Google repository maven url 'https://maven.google.com'
Som du kan se, innebærer den standardiserte arkitekturen foreslått av Android mange konsepter. Forvent ikke å ha en fullstendig forståelse av dette emnet ennå. Tross alt presenterer vi bare temaet. Men du har sikkert nok kunnskap til nå for å forstå logikken bak arkitekturen og rollene til de forskjellige arkitekturkomponentene.
Vi snakket om de fleste emnene knyttet til den foreslåtte Android-arkitekturen og dens komponenter; imidlertid detaljer om komponent implementering og noen tillegg, som Oppbevaringssted
klassen og Dagger 2-systemet kan ikke dekkes av denne første delen. Vi vil utforske disse temaene i de neste innleggene.
Ser deg snart!