Android introducerades för världen tillbaka 2005, och under de tolv års existensen har plattformen uppnått fantastisk framgång och blivit det mest installerade mobila operativsystemet. Under den tiden har 14 olika versioner av operativsystemet lanserats, och Android blir alltmer mogen. Ett väldigt viktigt område av plattformen fortsatte dock att ignoreras: ett standard arkitekturmönster som kan hantera plattformens egenskaper och enkelt nog att förstås och antas av den genomsnittliga utvecklaren.
Tja, bättre sent än aldrig. Vid den sista Google I / O-enheten bestämde Android-teamet slutligen att ta itu med detta problem och reagera på feedback från utvecklare över hela världen, meddelade en officiell rekommendation för en Android Application Architecture och gav byggstenarna att genomföra det: den nya arkitekturen Komponenter. Och ännu bättre lyckades de göra det utan att äventyra öppenheten i systemet som vi alla vet och älskar.
I den här handledningen utforskar vi den standardiserade arkitekturen som lagts fram av Android-teamet på Google I / O och tittar på huvudelementen i de nya arkitekturkomponenterna: Livscykel
, Viewmodel
, LifeData
, och Rum
. Vi kommer inte att betala för mycket uppmärksamhet åt koden, utan fokuserar på konceptet och logiken bakom dessa teman. Vi tar också en titt på några enkla utdrag, alla skrivna med Kotlin, ett fantastiskt språk som nu officiellt stöds av Android.
Om du bara börjar din resa som utvecklare är det möjligt att du inte vet exakt vad jag pratar om. När allt kommer omkring kan applikationsarkitekturen vara ett dunkelt tema först. Men tro mig, du kommer snart att lära dig dess betydelse! När en ansökan växer och blir mer komplex blir arkitekturen allt viktigare. Det kan bokstavligen göra ditt arbete till en salighet eller ett levande helvete.
Att lägga det ungefär är en applikationsarkitektur en konsekvent plan som måste göras innan utvecklingsprocessen börjar. Den här planen ger en karta över hur olika programkomponenter ska organiseras och knyts samman. Den presenterar riktlinjer som bör följas under utvecklingsprocessen och tvingar några uppoffringar (i allmänhet relaterade till fler klasser och panna) som till slut hjälper dig att konstruera en välskriven applikation som är mer testbar, utvidbar och underhållbar.
Programvaruarkitektur är processen att definiera en strukturerad lösning som uppfyller alla tekniska och operativa krav samtidigt som man optimerar gemensamma kvalitetsattribut som prestanda, säkerhet och hanterbarhet. Det handlar om en rad beslut baserade på ett brett spektrum av faktorer, och vart och ett av dessa beslut kan ha stor inverkan på kvaliteten, prestanda, underhåll och övergripande framgång för ansökan.
- Microsofts programvara för arkitektur och design
Bra arkitektur tar hänsyn till många faktorer, särskilt systemets egenskaper och gränser. Det finns många olika arkitektoniska lösningar där ute, alla med fördelar och nackdelar. Några nyckelbegrepp är emellertid vanliga mellan alla visioner.
Fram till den senaste Google I / O-enheten rekommenderade Android-systemet ingen specifik arkitektur för applikationsutveckling. Det betyder att du var helt fri att anta någon modell där ute: MVP, MVC, MVPP, eller ens inget mönster alls. Utöver det gav Android-ramen inte ens inbyggda lösningar för problem som skapades av systemet själv, speciellt komponentens livscykel.
Så om du ville anta ett Model View Presenter-mönster på din ansökan, behövde du komma med din egen lösning från början, skriva en hel del boilerplate-kod eller anta ett bibliotek utan officiellt stöd. Och det brist på standarder skapade många dåligt skrivna applikationer, med kodbaser som var svåra att underhålla och testa.
Som jag sa har denna situation kritiserats i flera år. Faktum är att jag nyligen skrev om det här problemet och hur man hanterar det i min How to Adopt Model View presenterare på Android-serien. Men det viktiga är att efter 12 långa år beslöt Android-laget äntligen att lyssna på våra klagomål och hjälpa oss med det här problemet.
Den nya Android Architecture Guide definierar några nyckelprinciper som en bra Android-applikation ska överensstämma med och föreslår också en säker väg för utvecklaren att skapa en bra app. I guiden anges emellertid uttryckligen att den presenterade rutten inte är obligatorisk, och i sista hand är beslutet personligt. Det är utvecklaren som ska bestämma vilken typ av arkitektur att anta.
Enligt guiden bör en bra Android-applikation ge en solid separation av problem och driva användargränssnittet från en modell. Vilken kod som inte hanterar gränssnitt för operativsystem eller operativsystem borde inte vara i en aktivitet eller fragment, eftersom du kan undvika många livscykelrelaterade problem eftersom du håller dem så rena som möjligt. När allt kommer ifrån kan systemet förstöra aktiviteter eller fragmenter när som helst. Dessutom ska data hanteras av modeller som är isolerade från användargränssnittet, och följaktligen från livscykelproblem.
Arkitekturen som Android rekommenderar kan inte enkelt märkas bland de standardmönster som vi känner till. Det ser ut som ett Model View Controller-mönster, men det är så nära kopplat till systemets arkitektur att det är svårt att märka varje element med de kända konventionerna. Det här är dock inte relevant, eftersom det är viktigt att det bygger på de nya arkitekturkomponenterna för att skapa en uppdelning av problem, med utmärkt testbarhet och underhåll. Och ännu bättre är det lätt att implementera.
För att förstå vad Android-teamet föreslår måste vi känna till alla element i arkitekturkomponenterna, eftersom de är de som kommer att göra det tunga för oss. Det finns fyra komponenter, var och en med en särskild roll: Rum
, Viewmodel
, LiveData
, och Livscykel
. Alla dessa delar har sitt eget ansvar, och de arbetar tillsammans för att skapa en solid arkitektur. Låt oss ta en titt på ett förenklat diagram över den föreslagna arkitekturen för att förstå det bättre.
Som ni kan se har vi tre huvudelement, var och en med sitt ansvar.
Aktivitet
och Fragment
representera Se
lager, som inte handlar om affärslogik och komplexa operationer. Den konfigurerar bara vyn, hanterar användarinteraktionen, och viktigast av allt, observerar och uppvisar LiveData
element som tagits från Viewmodel
.Viewmodel
observerar automatiskt Livscykel
synvinkel, upprätthållande av konsistens under konfigurationsändringar och andra Android-livscykelhändelser. Det krävs också att vi hämtar data från Repository
, som tillhandahålls som observerbar LiveData
. Det är viktigt att förstå att Viewmodel
aldrig hänvisar till Se
direkt och att uppdateringarna på data alltid görs av LiveData
entitet.Repository
är inte en speciell Android-komponent. Det är en enkel klass, utan någon särskild implementering, som ansvarar för att hämta data från alla tillgängliga källor, från en databas till webbtjänster. Den hanterar alla dessa data, generellt omvandlar dem till observerbara LiveData
och göra dem tillgängliga för Viewmodel
.Rum
databasen är ett SQLite kartläggning bibliotek som underlättar processen att hantera en databas. Den skriver automatiskt ett ton keddeplatta, kontrollerar fel vid sammanställningstiden, och bäst av allt kan det direkt returnera frågor med observerbara LiveData
.Jag är säker på att du har märkt att vi har pratat mycket om observerbarhet. Observermönstret är en av baserna av LiveData
element och Livscykel
medvetna komponenter. Detta mönster gör det möjligt för ett objekt att meddela en lista över observatörer om eventuella förändringar i dess tillstånd eller data. Så när en aktivitet observerar en LiveData
enheten kommer det att få uppdateringar när den data genomgår någon form av ändring.
En annan Android-rekommendation är att konsolidera sin arkitektur med ett Dependency Injection-system, till exempel Googles Dagger 2 eller med hjälp av Service Locator-mönstret (vilket är mycket enklare än DI men utan många av dess fördelar). Vi kommer inte att täcka DI eller Service Locator i denna handledning, men Envato Tuts + har några utmärkta handledning om dessa teman. Men var försiktig att det finns några särdrag att arbeta med Dagger 2 och Android Components som kommer att förklaras i den andra delen av serien.
Vi måste dyka djupt in i aspekterna av de nya komponenterna för att kunna förstå och anta denna arkitekturmodell. Vi kommer emellertid inte att komma in i alla detaljer i denna handledning. På grund av komplexiteten hos varje element, i den här handledningen talar vi bara om den allmänna idén bakom varje och tittar på några förenklade kodutdrag. Vi försöker täcka noggrann mark för att presentera komponenterna och komma igång. Men frukta inte, för framtida artiklar i denna serie kommer att gräva djupt och täcka alla detaljer i arkitekturkomponenterna.
De flesta av Android-appkomponenterna har livscykler kopplade till dem, vilka hanteras direkt av själva systemet. Fram till nyligen var det upp till utvecklaren att övervaka komponenternas tillstånd och agera därefter, initiera och avsluta uppgifter vid rätt tidpunkt. Det var dock väldigt enkelt att bli förvirrad och göra misstag relaterade till denna typ av operation. Men android.arch.lifecycle
paketet förändrats allt det.
Nu har Aktiviteter och Fragmenter a Livscykel
objekt kopplat till dem som kan observeras av LifecycleObserver
klasser, som a Viewmodel
eller något objekt som implementerar detta gränssnitt. Det betyder att observatören kommer att få uppdateringar om tillståndsändringar i objektet som det observerar, som när en aktivitet är pausad eller när den börjar. Det kan även kontrollera det observerade objektets nuvarande tillstånd. Så det är mycket lättare att hantera verksamheter som måste överväga ramlivscyklerna.
För nu, för att skapa en Aktivitet
eller Fragment
som överensstämmer med denna nya standard måste du förlänga a LifecycleActivity
eller LifecycleFragment
. Det är dock möjligt att det inte alltid kommer att vara nödvändigt eftersom Android-teamet syftar till att helt integrera dessa nya verktyg med dess ramverk.
klass MainActivity: LifecycleActivity () överstyra kul påCreate (savedInstanceState: Bundle?) super.onCreate (savedInstanceState) setContentView (R.layout.activity_main)
De LifecycleObserver
mottar Livscykel
händelser och kan reagera genom annotering. Ingen metodöverstyrning är nödvändig.
klass MainActivityObserver: LifecycleObserver, AnkoLogger @OnLifecycleEvent (Lifecycle.Event.ON_RESUME) roligt påResume () info ("onResume") @OnLifecycleEvent (Lifecycle.Event.ON_PAUSE) roligt påPause () info ("onPause")
LiveData
KomponentDe LiveData
komponent är en datahållare som innehåller ett värde som kan observeras. Med tanke på att observatören har lämnat en Livscykel
under LiveData
instansiering, LiveData
kommer att uppträda enligt Livscykel
stat. Om observatören är Livscykel
tillståndet är SATTE IGÅNG
eller FORTSATT
, observatören är aktiva
; annars är det inaktiv
.
LiveData
vet när data har ändrats och även om observatören är aktiva
och bör få en uppdatering. En annan intressant egenskap hos LiveData
är att den kan ta bort observatören om den är i en Lifecycle.State.DESTROYED
tillstånd, undviker minnesläckor när det observeras av aktiviteter och fragment.
en LiveData
måste genomföra onActive
och onInactive
metoder.
klass LocationLiveData (context: Context): LiveData(), AnkoLogger, LocationListener Private val locationManager: LocationManager = context.getSystemService (Context.LOCATION_SERVICE) som LocationManager åsidosätta roligt onActive () info ("onActive") locationManager.requestLocationUpdates (LocationManager.GPS_PROVIDER, 0, 0f, detta) åsidosätta roliga onInactive () info ("onIctive") locationManager.removeUpdates (this) // ...
Att observera a LiveData
komponent, du måste ringa observatör (LifecycleOwner, Observer
.
klass MainActivity: LifecycleActivity (), AnkoLogger fun observeLocation () val location = LocationLiveData (this) location.observe (detta Observer plats -> info ("plats: $ plats"))
Viewmodel
KomponentEn av de viktigaste klasserna i de nya arkitekturkomponenterna är Viewmodel
, som är utformad för att hålla data som är relaterade till användargränssnittet, upprätthåller dess integritet under konfigurationsändringar som skärmrotationer. De Viewmodel
kan prata med Repository
, få LiveData
från den och göra den tillgänglig i sin tur att bli observerad av vyn. Viewmodel
behöver inte göra nya samtal till Repository
efter konfigurationsändringar, vilket optimerar koden mycket.
För att skapa en visningsmodell, förlänga Viewmodel
klass.
klass MainActivityViewModel: ViewModel () private var notes: MutableLiveData>? = noll rolig getNotes (): LiveData
> if (notes == null) notes = MutableLiveData
> () loadNotes () returnoteringar !! privata roliga loadNotes () // gör async-operation för att hämta anteckningar
För att komma åt från en vy kan du ringa ViewProviders.of (Aktivitet | Fragment) .Skaffa (Viewmodel :: klass)
. Denna fabriksmetod returnerar en ny instans av Viewmodel
eller få den behållna, efter behov.
klass MainActivity: LifecycleActivity (), AnkoLogger överrätta kul påCreate (savedInstanceState: Bundle?) super.onCreate (savedInstanceState) setContentView (R.layout.activity_main) val viewModel = ViewModelProviders.of (this) .get (MainActivityViewModel :: class. java) viewModel.getNotes (). observera (detta Observer noteringar -> info ("anteckningar: $ noter"))
Rum
KomponentAndroid stödde SQLite från början; Men för att få det att fungera var det alltid nödvändigt att skriva mycket pannplatta. Dessutom lagrade SQLite inte POJOS (vanliga Java-objekt) och kontrollerade inte frågorna vid kompileringstid. Vidare kommer Rum
att lösa dessa problem! Det är ett SQLite kartläggningsbibliotek som kan fortsätta Java POJOs, konverterar direkt frågor till objekt, kontrollerar fel vid kompileringstid och producerar LiveData
observerbarhet från sökresultat. Rum
är ett Objekt Relational Mapping-bibliotek med några coola Android-extramaterial.
Hittills kan du göra det mesta av vad Rum
kan använda andra ORM Android-bibliotek. Men ingen av dem är officiellt stödda och, viktigast av allt, kan de inte producera LifeData
resultat. De Rum
Biblioteket passar perfekt som det ihållande lagret på den föreslagna Android-arkitekturen.
För att skapa en Rum
databas, behöver du en @Entitet
att fortsätta, vilket kan vara någon Java POJO, a @Dao
gränssnitt för att göra frågor och inmatnings- / utmatningsoperationer, och a @Databas
abstrakt klass som måste förlängas RoomDatabase
.
@Entity class Note @PrimaryKey var id: Long? = null var text: String? = Noll var datum: Långt? = null
@Dao-gränssnittet NoteDAO @Insert (onConflict = OnConflictStrategy.REPLACE) Fun InsertNote (notera: Obs): Long @Update (onConflict = OnConflictStrategy.REPLACE) roligt uppdateringNote (notera: Notera): Int @Delete Fun deleteNote : Int @Query ("VÄLJ * FRÅN NOTT") Fun FindAllNotes (): LiveData// på Kotlin ändras sökargumenten // till arg [N], varvid N är argumentet nummer. // på Java antar argumentet sitt ursprungliga namn @Query ("VÄLJ * FRÅN notera WHERE id =: arg0") fun findNoteById (id: Long): LiveData
@Database (enheter = arrayOf (Obs :: klass), version = 1) abstrakt klass Databas: RoomDatabase () abstrakt rolig noteringDAO (): NoteDAO
För att nu använda de nya arkitekturkomponenterna måste du först lägga till Google-arkivet i din build.gradle
fil. För mer information, se den officiella guiden.
allprojects repositories jcenter () // Lägg till Google repository maven url 'https://maven.google.com'
Som du kan se, innebär den standardiserade arkitekturen som föreslås av Android många koncept. Förvänta dig inte att ha en fullständig förståelse av detta ämne än. När allt kommer omkring introducerar vi bara temat. Men du har förvisso tillräckligt med kunskap för att förstå logiken bakom arkitekturen och rollerna i de olika arkitekturkomponenterna.
Vi pratade om de flesta ämnen som rör den föreslagna Android-arkitekturen och dess komponenter. dock detaljer om komponentens genomförande och några extrafunktioner, som Repository
klass och Dagger 2-systemet kan inte omfattas av denna första del. Vi utforskar dessa teman i nästa inlägg.
Ses snart!