Implementere en Event Bus med LiveData

Hva du skal skape

På den siste Google I / O, lanserte Android-teamet et sett med kraftige Android Architecture-komponenter. De kaller det:

En samling av biblioteker som hjelper deg med å designe robuste, testbare og vedlikeholdbare apper. Start med klasser for å administrere UI-komponentens livssyklus og håndtering av persistens av data.

Hvis du ikke har lært om dem, er du sterkt anbefalt å sjekke ut vår fantastiske serie her på Envato Tuts + om Android Architecture Components av Tin Megali. Pass på at du dykker inn! 

I denne veiledningen vil jeg vise deg hvordan du bruker LiveData komponenter fra Android Architectural Components for å lage en hendelse buss. En hendelsesbuss kan brukes til å kommunisere effektivt mellom Android-komponenter eller mellom lag av søknaden din, for eksempel å kommunisere til en Aktivitet fra en IntentService at en fil er ferdig nedlasting. 

Vi bygger en veldig enkel app som utløser en IntentService å gjøre noe arbeid - fra en Aktivitet. Våre IntentService vil da kommunisere tilbake til Aktivitet når arbeidet er fullført. Vår kommunikasjonskanal kommer fra LiveData bibliotek. 

Forutsetninger

For å kunne følge denne opplæringen må du:

  • Android Studio 3.0 eller høyere
  • Kotlin plugin 1.1.51 eller høyere
  • en grunnleggende forståelse av Android Architectural Components (spesielt LiveData komponent)
  • en grunnleggende forståelse av en hendelsesbuss

Du kan også lære alle Kotlin-språkene i Kotlin From Scratch-serien.

  • Kotlin From Scratch: Variabler, Grunntyper og Arrays

    Kotlin er et moderne programmeringsspråk som kompilerer til Java bytecode. Det er gratis og åpen kildekode, og lover å gjøre koding for Android enda morsommere.
    Chike Mgbemena
    Kotlin
  • Kotlin fra grunnen: Klasser og objekter

    Få en introduksjon til objektorientert programmering i Kotlin ved å lære om klasser: Konstruktører og egenskaper, avstøpning og avanserte klassefunksjoner.
    Chike Mgbemena
    Kotlin

1. Opprett et Android Studio-prosjekt

Brann opp Android Studio 3 og opprett et nytt prosjekt med en tom aktivitet som heter Hoved aktivitet

2. Legg til livscykelkomponentene

Etter å ha opprettet et nytt prosjekt, spesifiser du Livssyklus og LiveData gjenstander i appmodulets build.gradle. Vær oppmerksom på at de nye arkitektoniske komponentene i denne skrivingen nå er i en stabil versjon. Så dette betyr at du kan begynne å bruke dem i produksjonsprogrammer. 

avhengighet implementering fileTree (dir: 'libs', inkluderer: ['* .jar']) implementering "org.jetbrains.kotlin: kotlin-stdlib-jre7: $ kotlin_version" implementering "com.android.support:appcompat-v7: 26.1.0 'implementering' android.arch.lifecycle: kjøretid: 1.0.3 "implementering" android.arch.lifecycle: utvidelser: 1.0.0 "

Disse artefakter er tilgjengelig på Googles Maven-depot. 

allprojects repositories google () jcenter ()

Ved å legge til avhengighetene har vi lært gradvis hvordan man finner biblioteket. Pass på at du husker å synkronisere prosjektet ditt etter å ha lagt dem til. 

3. Opprett LifecycleOwner Aktivitetsunderklasse

Her vår Hoved aktivitet implementerer LifecycleOwner grensesnitt. 

importer android.arch.lifecycle.Lifecycle import android.arch.lifecycle.LifecycleOwner importere android.arch.lifecycle.LifecycleRegistry import android.arch.lifecycle.Observer importere android.content.Intent importere android.os.Bundle import android.support.v7 .app.AppCompatActivity import android.view.View import android.widget.Button import android.widget.TextView klasse MainActivity: AppCompatActivity (), LifecycleOwner private val register = LifecycleRegistry (this) overstyrer moro onCreate (savedInstanceState: Bundle?) super .onCreate (savedInstanceState) setContentView (R.layout.activity_main) registry.handleLifecycleEvent (Lifecycle.Event.ON_CREATE) overstyre morsomt getLifecycle (): Lifecycle = registret overstyrer moro påStart () super.onStart () registry.handleLifecycleEvent (Lifecycle. Event.ON_START) overstyr moro onResume () super.onResume () registry.handleLifecycleEvent (Lifecycle.Event.ON_RESUME) overstyr moro onPause () super.onPause () registry.handleLifecycleEvent (Lifecycle.Event.ON_PAUSE)  overstyr moro onStop () super.onStop () registry.handleLifecycleEvent (Lifecycle.Event.ON_STOP) overstyr moro onDestroy () super.onDestroy () registry.handleLifecycleEvent (Lifecycle.Event.ON_DESTROY) 

Vår aktivitet håndterer bare de vanlige aktivitetens livssyklushendelser. Inne i hver av livssyklus hendelsene, kaller det registry.handleLifecycleEvent (), passerer den tilsvarende hendelsen som en parameter.   

4. Lag oppsettet

Vi har bare en Knapp som utløser tjenesten. EN TextView (usynlig som standard) viser teksten "Arbeid ferdig!" når tjenesten kommuniserer til vår Hoved aktivitet

  

5. Initialiser Widgets

Vi erklærte vår doWorkButton og resultTextView eiendommer inne i Hoved aktivitet klasse med lateinit modifier. Vi initialiserer dem deretter inne i onCreate () metode. når som helst doWorkButton er klikket, vi deaktiverer det (for å hindre å klikke på knappen mer enn en gang) og starte vår MyIntentService (vi kommer til det snart). 

Klasse MainActivity: AppCompatActivity (), LifecycleOwner Private Sentinit var doWorkButton: Knapp Privat Sentinit var resultTextView: TextView overstyr moro onCreate (savedInstanceState: Bundle?) // ... doWorkButton = findViewById (R.id.btn_download) doWorkButton.setOnClickListener doWorkButton. isEnabled = false resultTextView.visibility = View.INVISIBLE val serviceIntent = Intent (dette, MyIntentService :: class.java) startService (serviceIntent) resultTextView = findViewById (R.id.tv_result) // ...

6. Lag den tilpassede hendelsesklassen

Vi lager bare en enkel hendelse-meldingsklasse som vi ønsker å passere rundt på arrangementsbussen (eller LiveData). 

dataklasse CustomEvent (val eventProp: String)

Du kan legge til flere eiendommer til denne klassen hvis du vil. 

7. Service Implementering

Vi implementerte en IntentService kalt MyIntentService. Husk at IntentService lever utenfor aktivitetsområdet og har en bakgrunnstråd, så det anbefales å utføre tidkrevende oppgaver som å laste ned eller hente eksterne data via en API inne i den.  

Vær imidlertid oppmerksom på at i Android 8.0 hvis du ikke lager din IntentService en forgrunns tjeneste ved å bruke startForeground (), Android-systemet tillater ikke at tjenesten din går over 1 minutt, eller den stoppes umiddelbart. Denne mekanismen er å effektivt administrere systemressurser som batterilevetid. Hvis appen din målretter mot Android 8.0, anbefales du å bruke JobIntentService i stedet. 

importere android.app.IntentService import android.arch.lifecycle.MutableLiveData import android.content.Intent importere android.os.SystemClock klasse MyIntentService: IntentService ("MyIntentService") følgesvennobjekt var BUS = MutableLiveData simulere arbeidet SystemClock.sleep (3000) // antar at arbeidet er gjort val event = CustomEvent ("value") hvis (BUS.hasActiveObservers ()) BUS.postValue (hendelse) annet // show notification

Vi lager et navnløst følgesvennobjekt hvis kompanjonsklasse er MyIntentService. Dette følgesvennobjektet har en eiendom som heter BUSS, som er en forekomst av MutableLiveData.  Husk at følgesvenn objekter er singletoner, så dette betyr at bare en enkelt forekomst av BUSS eksisterer. Vi passerte også vår CustomEvent som et type argument til generisk MutableLiveData klasse. 

Husk at MutableLiveData klassen er en underklasse av LiveData-og har en metode kalt postValue () som kan kalles fra en bakgrunnstråd. 

offentlig klasse MutableLiveData utvider LiveData @Override public void postValue (T verdi) super.postValue (verdi);  @Override public void setValue (T-verdi) super.setValue (value); 

Innsiden onHandleIntent (), Vi har vår forretningslogikk. Husk at denne metoden kalles på en bakgrunnstråd (en av de store forskjellene mellom en IntentService og en normal Service). De IntentService slutter umiddelbart av seg selv når onHandleIntent () Metoden fullfører jobben sin.  

I vårt eget tilfelle simulerer vi arbeidet som gjøres (dette arbeidet kan være en nedlasting av filer eller kommunisere med en ekstern API) ved å sove den gjeldende tråden i 30 sekunder. Vi sjekket da om vår BUSS Har noen aktive observatører å bruke hasActiveObservers () metode. Hvis det er noen, informer og send vår hendelsesmelding til dem ved å bruke metoden postValue (), Ellers kan vi bare vise et varsel (dette var ikke kodet i eksemplet ovenfor for korthetens skyld). 

Husk å inkludere tjenesten i manifestfilen din.

8. Observer Implementering

Vi trenger minst en observatør for at vår mekanisme skal være nyttig. Så inne i Hoved aktivitet klasse, vi skal abonnere på en anonym observatør. 

klasse MainActivity: AppCompatActivity (), LifecycleOwner // ... overstyr moro onCreate (savedInstanceState: Bundle?) // ... MyIntentService.BUS.observe (dette, Observer event -> resultTextView.visibility = View.VISIBLE downloadButton.isEnabled = true Log.d ("MainActivity", event? .EventProp)) // ...

Inne i onCreate () av Hoved aktivitet, vi fikk arrangementsbussen BUSS fra MyIntentService. Deretter registrerte vi en observatør for arrangementsbussen (dvs.. LiveData) bruker observere() metode. Deretter registrerte og innramte vi en anonym observatør ved å bruke Hoved aktivitet som LifecycleOwner. Denne anonyme observatøren blir varslet når et av følgende skjer:

  • Det er allerede data tilgjengelig i LiveData når den abonnerer. 
  • Dataene inne i LiveData blir endret. 

Når en av disse oppstår, får vi begivenhet data (fra LiveData) på hovedapplikasjonen tråden som inngang til lambda. Vi gjør følgende i lambdas kropp:

  • Lage resultTextView synlig.
  • Aktiver doWorkButton.
  • Logg på vår egendefinerte hendelsesegenskap eventProp verdi til Logcat.

Husk følgende om LiveData:

  • Når en ny observatør er knyttet til vår LiveData etter en konfigurasjonsendring, LiveData vil sende de siste dataene det mottok til observatøren - selv uten at vi uttrykkelig fortalte det å gjøre det. Med andre ord gjør det dette automatisk. 
  • Når LifecycleOwner blir ødelagt, blir observatøren automatisk avmeldt. 
  • Endelig, LiveData er en observerbar som er livscyklusbevisst. Ifølge dokumentene:
LiveData er en observerbar dataholderklasse. I motsetning til en regelmessig observerbar, er LiveData livssyklusbevisst, noe som betyr at den respekterer livscyklusen til andre appkomponenter, for eksempel aktiviteter, fragmenter eller tjenester. Denne bevisstheten sikrer at LiveData bare oppdaterer app-komponentobservatører som befinner seg i en aktiv livscyklusstat.

9. Teste appen

Til slutt kan du kjøre appen! Klikk på Gjør arbeid knappen og etter 30 sekunder ser du resultatet. 

Du kan få den komplette kildekoden fra vår GitHub repo.

Konklusjon

I denne opplæringen lærte du hvordan du enkelt kunne bruke LiveData komponenter fra Android Architectural Components for å lage en hendelse-buss for å kommunisere effektivt med komponentene i appen din. 

Jeg antar at du er klar over andre biblioteker du kan bruke til samme formål, for eksempel Android LocalBroadcastManager eller den populære greenrobot EventBus, for å implementere en hendelsesbuss i Android-applikasjonen. Du kan se at du bruker LiveData i stedet er å foretrekke for dem - fordi du unngår å skrive boilerplate eller verbose kode, og LiveData gir deg bedre fleksibilitet. 

For å lære mer om koding for Android, sjekk ut noen av våre andre kurs og opplæringsprogrammer her på Envato Tuts+!