Implementarea unui bus de evenimente cu LiveData

Ce veți crea

La ultimul Google I / O, echipa Android a lansat un set de componente Android de arhitectură puternică. Ei o numesc:

O colecție de biblioteci care vă ajută să proiectați aplicații robuste, verificabile și întreținute. Începeți cu clase pentru gestionarea ciclului de viață al componentei UI și manipularea persistenței datelor.

Dacă nu ați învățat despre ele, vă recomandăm să consultați seria minunată de aici despre Envato Tuts + despre componentele Android Architecture de Tin Megali. Asigurați-vă că vă plimbați! 

În acest tutorial, vă voi arăta cum să utilizați LiveData componente din Componentele arhitecturale Android pentru a crea o magistrală de evenimente. Un bus de evenimente poate fi utilizat pentru a comunica în mod eficient între componentele Android sau între straturile aplicației dvs. - de exemplu, comunicarea cu o aplicație Activitate de la un IntentService că un fișier a terminat descărcarea. 

Vom construi o aplicație foarte simplă care declanșează o IntentService pentru a face ceva de lucru - de la Activitate. Al nostru IntentService va comunica apoi înapoi la Activitate când lucrarea este finalizată. Canalul nostru de comunicare va fi de la LiveData bibliotecă. 

Cerințe preliminare

Pentru a putea urma acest tutorial, veți avea nevoie de:

  • Android Studio 3.0 sau o versiune ulterioară
  • Kotlin plugin 1.1.51 sau mai mare
  • o înțelegere de bază a componentelor Android de arhitectură (în special LiveData componentă)
  • o înțelegere de bază a unui autobuz de evenimente

De asemenea, puteți afla toate intrările și ieșirile din limba Kotlin în seria mea Kotlin From Scratch.

  • Kotlin de la zero: variabile, tipuri de bază și matrice

    Kotlin este un limbaj de programare modern care se compilează la Java bytecode. Este gratuit și open source, și promite să facă codificarea pentru Android chiar mai distractiv.
    Chike Mgbemena
    Kotlin
  • Kotlin de la zero: clase și obiecte

    Obțineți o introducere în programarea orientată pe obiecte în Kotlin, învățând despre clase: constructori și proprietăți, casting și caracteristici avansate de clasă.
    Chike Mgbemena
    Kotlin

1. Creați un proiect Android Studio

Activați Android Studio 3 și creați un nou proiect cu o activitate goală numită Activitate principala

2. Adăugați componentele ciclului de viață

După crearea unui nou proiect, specificați Ciclu de viață si LiveData artefacte în modulul dvs. de aplicație build.gradle. Rețineți că începând cu această scriere, noile componente arhitecturale sunt acum într-o versiune stabilă. Deci, acest lucru înseamnă că puteți începe să le utilizați în aplicații de producție. 

dependență implementare fileTree (dir: 'libs', include: ['* .jar']) implementare "org.jetbrains.kotlin: kotlin-stdlib-jre7: $ kotlin_version" implementare com.android.support:appcompat-v7: 26.1.0 "implementare" android.arch.lifecycle: runtime: 1.0.3 "implementare" android.arch.lifecycle: extensii: 1.0.0 "

Aceste artefacte sunt disponibile la depozitul Google Maven. 

toate proiectele repositories google () jcenter ()

Prin adăugarea dependențelor, am învățat cum să găsească biblioteca. Asigurați-vă că vă amintiți să vă sincronizați proiectul după ce le-ați adăugat. 

3. Creați LifecycleOwner Activitate Subclasă

Aici, noi Activitate principala implementează LifecycleOwner interfață. 

importați android.arch.lifecycle.Lifecycle import șiroid.arch.lifecycle.LifecycleOwner import android.arch.lifecycle.LifecycleRegistry import android.arch.lifecycle.Observer import android.content.Intent Import import șiroid.os.Bundle android.support.v7 .app.AppCompatActivity import android.view.View import android.widget.Button de import android.widget.TextView class MainActivity: AppCompatActivity (), LifecycleOwner private val registry = LifecycleRegistry (aceasta) suprascrie fun onCreate (savedInstanceState: Bundle?) super .construcțiune (savedInstanceState) setContentView (R.layout.activity_main) registry.handleLifecycleEvent (Lifecycle.Event.ON_CREATE) suprascrie distracție getLifecycle (): Lifecycle = suprascrie registrul funny onStart () super.onStart () registry.handleLifecycleEvent (Lifecycle. Event.ON_START) suprascrie distracția onResume () super.onResume () registry.handleLifecycleEvent (Lifecycle.Event.ON_RESUME) suprascrie fun onPause () super.onPause () registry.handleLifecycleEvent (Lifecycle.Event.ON_PAUSE)  suprascrie distracția onStop () super.onStop () registry.handleLifecycleEvent (Lifecycle.Event.ON_STOP) suprascrie distracția onDestroy () super.onDestroy () registry.handleLifecycleEvent (Lifecycle.Event.ON_DESTROY) 

Activitatea noastră gestionează pur și simplu evenimentele standard ale ciclului de viață al activității. În cadrul fiecărui eveniment de ciclu de viață, acesta cheamă registry.handleLifecycleEvent (), trecerea evenimentului corespunzător ca parametru.   

4. Creați aspectul

Pur și simplu avem Buton care declanșează serviciul. A TextView (invizibil în mod implicit) afișează textul "Lucrările au fost finalizate!" când serviciul comunică cu noi Activitate principala

  

5. Inițializați Widget-urile

Ne-am declarat doWorkButton și resultTextView proprietăți în interiorul Activitate principala clasa cu lateinit modificator. Atunci le inițializăm în interiorul onCreate () metodă. Ori de cate ori doWorkButton se face clic pe acesta, îl dezactivați (pentru a împiedica apăsarea butonului de mai multe ori) și începeți MyIntentService (vom ajunge la asta în scurt timp). 

class MainActivity: AppCompatActivity (), LifecycleOwner privat lateinit var doWorkButton: Buton privat lateinit var resultTextView: TextView suprascrie distracție onCreate (savedInstanceState: Bundle?) // ... doWorkButton = findViewById (R.id.btn_download) doWorkButton.setOnClickListener doWorkButton. isEnabled = rezultat falseTextView.visibility = View.INVISIBLE val serviceIntent = Intent (aceasta, MyIntentService :: class.java) startService (serviceIntent) resultTextView = findViewById (R.id.tv_result) // ...

6. Creați Clasa de evenimente personalizate

Tocmai creăm o clasă de mesaje simple pentru eveniment pe care dorim să o transmitem în autobuzul evenimentului (sau LiveData). 

clasa de date CustomEvent (val eventProp: String)

Puteți adăuga mai multe proprietăți în această clasă dacă doriți. 

7. Implementarea serviciului

Am implementat un IntentService numit MyIntentService. Sa nu uiti asta IntentService trăiește în afara sferei de activitate și are un fir de fundal, deci este recomandat să efectuați sarcini consumatoare de timp, cum ar fi descărcarea sau preluarea datelor la distanță prin intermediul unui API din interiorul acestuia.  

Cu toate acestea, rețineți că în Android 8.0 dacă nu vă faceți IntentService un serviciu în prim plan prin utilizarea startForeground (), sistemul Android nu va permite serviciului dvs. să ruleze mai mult de 1 minut - sau altfel acesta va fi oprit imediat. Acest mecanism este de a gestiona eficient resursele sistemului, cum ar fi durata de viață a bateriei. Dacă aplicația dvs. vizează Android 8.0, vi se recomandă să utilizați locația JobIntentService. 

importați importul android.app.IntentService android.arch.lifecycle.MutableLiveData importați android.content.Intent importați class android.os.SystemClock MyIntentService: IntentService ("MyIntentService") obiect companion var BUS = MutableLiveData(//) simulează munca SystemClock.sleep (3000) // presupunând că lucrarea este făcută val event = CustomEvent ("value") dacă (BUS.hasActiveObservers ()) BUS.postValue (eveniment) altceva // afișare notificare

Creăm un obiect insoțesc fără nume, a cărui clasă de însoțitoare este MyIntentService. Acest obiect însoțitor are o proprietate numită AUTOBUZ, care este un exemplu de MutableLiveData.  Amintiți-vă că obiectele companion sunt singletons, deci înseamnă că doar o singură instanță de AUTOBUZ există. Am trecut și noi CustomEvent ca argument de tip pentru generic MutableLiveData clasă. 

Amintiți-vă că MutableLiveData clasa este o subclasă de LiveData-și are o metodă numită postValue () care poate fi apelat dintr-un fir de fundal. 

clasa publică MutableLiveData extinde LiveData @Override public void postValue (valoare T) super.postValue (valoare);  @Override public void setValue (valoare T) super.setValue (valoare); 

Interior onHandleIntent (), avem logica noastră de afaceri. Amintiți-vă că această metodă este chemată pe un fir de fundal (una dintre diferențele majore dintre o IntentService și un normal Serviciu). IntentService se încheie imediat de la sine atunci când onHandleIntent () metoda își termină treaba.  

În cazul nostru, simulează munca făcută (această lucrare poate fi descărcarea unui fișier sau comunicarea cu un API la distanță) prin somnirea firului curent timp de 30 de secunde. Apoi am verificat dacă noi AUTOBUZ are orice observatori activi care folosesc hasActiveObservers () metodă. Dacă există vreunul, anunțați-i și transmiteți mesajul evenimentului acestora utilizând metoda postValue (), sau altfel putem să arătăm doar o notificare (acest lucru nu a fost codificat în exemplul de mai sus pentru dragul brevetului). 

Nu uitați să includeți serviciul în fișierul manifest.

8. Implementarea observatorului

Avem nevoie de cel puțin un observator pentru ca mecanismul nostru să fie util. Deci, în interiorul Activitate principala clasa, ne vom abona la un observator anonim. 

class MainActivity: AppCompatActivity (), LifecycleOwner // ... suprascrie fun onCreate (savedInstanceState: Bundle?) // ... MyIntentService.BUS.observe (acest lucru, Observer event -> resultTextView.visibility = View.VISIBLE downloadButton.isEnabled = true Log.d ("MainActivity", eveniment? .EventProp)) // ...

În interiorul onCreate () de Activitate principala, am primit autobuzul de evenimente AUTOBUZ din MyIntentService. Apoi am înregistrat un observator pentru autobuzul de evenimente (adică. LiveData) folosind observa() metodă. Apoi, am înregistrat și a subliniat un observator anonim, folosind Activitate principala la fel de LifecycleOwner. Acest observator anonim devine notificat atunci când se întâmplă oricare dintre următoarele:

  • Există deja date disponibile în LiveData atunci când subscrie. 
  • Datele din interiorul LiveData se modifică. 

Când se întâmplă oricare dintre acestea, ajungem eveniment date (de la LiveData) pe firul principal de aplicație ca intrare la lambda. Apoi facem următoarele în interiorul corpului lambdei:

  • Fă resultTextView vizibil.
  • Activați doWorkButton.
  • Conectați proprietatea evenimentului personalizat eventProp valoare pentru Logcat.

Rețineți următoarele despre LiveData:

  • Atunci când un nou observator este atașat la nostru LiveData după o schimbare de configurație, LiveData va trimite ultimele date pe care le-a primit observatorului - chiar și fără ca noi să-i spunem în mod explicit să facă acest lucru. Cu alte cuvinte, face acest lucru automat. 
  • Cand LifecycleOwner este distrus, observatorul va fi automat dezabonat. 
  • In cele din urma, LiveData este o observabilă care este conștientă de ciclul de viață. Potrivit documentelor:
LiveData este o clasă deținător de date observabilă. Spre deosebire de o observabilă obișnuită, LiveData este conștientă de ciclul de viață, ceea ce înseamnă că respectă ciclul de viață al altor componente ale aplicației, cum ar fi activități, fragmente sau servicii. Această conștientizare asigură faptul că LiveData actualizează numai observatorii componentelor de aplicație care se află într-o stare de ciclu de viață activă.

9. Testarea aplicației

În cele din urmă, puteți rula aplicația! Apasă pe Munceste și după 30 de secunde, veți vedea rezultatul. 

Puteți obține codul sursă complet din repo GitHub.

Concluzie

În acest tutorial, ați învățat cum să utilizați ușor LiveData componente ale Componentelor arhitecturale Android pentru a crea un bus de evenimente - astfel încât să comunice eficient cu componentele aplicației dvs.. 

Presupun că sunteți conștient de alte biblioteci pe care le puteți utiliza în același scop, cum ar fi Android LocalBroadcastManager sau popularul EventBus greenrobot pentru implementarea unui bus de evenimente în aplicația Android. Puteți vedea că folosind LiveData în schimb este preferabil pentru ei - pentru că evitați să scrieți codul de bare sau codul verbose și LiveData vă oferă o mai mare flexibilitate. 

Pentru a afla mai multe despre codificarea pentru Android, consultați câteva dintre celelalte cursuri și tutoriale de aici, pe Envato Tuts+!

Cod