Coding Funcțional Apps Android în Kotlin Lambdas, Null Safety & More

În această serie de trei părți, am analizat în detaliu Kotlin, un limbaj de programare modern pentru aplicațiile Android care rulează în Java Virtual Machine (JVM). 

În timp ce Kotlin este departe de singura limbă de programare alternativă proiectată să ruleze pe JVM, ea are multe de oferit dezvoltatorilor Android. Deci, dacă v-ați simțit recent frustrat cu partea Java de dezvoltare Android, atunci veți dori să luați în considerare oferirea lui Kotlin.

În primele două rate, am acoperit următoarele:

  • Java vs. Kotlin: Ar trebui să utilizați Kotlin pentru dezvoltarea Android? În acest articol introductiv, ne-am uitat la ceea ce a oferit Kotlin dezvoltatorilor Android, precum și unele dezavantaje potențiale pe care trebuie să le cunoașteți înainte de a decide dacă Kotlin este potrivit pentru dvs..

  • Coding Funcțional Apps Android în Kotlin: Noțiuni de bază. În acest post, am analizat cum să configurați Android Studio pentru a sprijini codul Kotlin, a creat o aplicație Android scrisă în întregime în Kotlin, ne-am familiarizat cu sintaxa de bază a lui Kotlin și chiar am văzut cum trecerea la Kotlin poate însemna că nu trebuie să mai scrieți altul findViewById din nou.

Acum că sunteți în poziția în care puteți înlocui porțiunile Java ale proiectelor dvs. cu codul Kotlin care are același rezultat final, hai să mergem mai departe și să ne uităm la unele zone în care Kotlin are avantaj peste Java.

În această ultimă tranșă, vom explora unele dintre cele mai avansate caracteristici Kotlin care vă permit să efectuați sarcini care ar fi fie mult mai detaliate în Java, fie nu pot fi realizate doar cu Java.

Până la sfârșitul acestui articol, veți ști cum să utilizați Kotlin pentru a tăia o tonă de cod de boilerplate din proiectele dvs., pentru a extinde clasele existente cu noi funcționalități și pentru a le face pe aceia frustranți NullPointerExceptione un lucru din trecut.  

Nu mai multe Nulls

De câte ori ai intrat într-un NullPointerException în timp ce testați codul dvs.? Astăzi, este destul de clar că permiterea dezvoltatorilor de a aloca null unei referințe de obiect nu a fost Cel mai bun design alegere! Încercarea de a utiliza o referință de obiect care are o valoare nulă este o sursă imensă de bug-uri în multe limbi de programare diferite, inclusiv Java. De fapt, NullPointerException a fost o sursă imensă de enervare pe care Java 8 a adăugat-o @NonNull adnotare special pentru a încerca și remedia acest defect în sistemul său de tip.

Problema constă în faptul că Java vă permite să setați orice variabilă de tip de referință la null - dar dacă în orice moment încercați să utilizați o referință care indică nul, atunci variabila nu va ști unde să se uite deoarece obiectul nu există de fapt. În acest moment, JVM nu poate continua calea normală de executare - aplicația dvs. se va prăbuși și veți întâlni o NullPointerException. Încercarea de a apela o metodă pe o referință nulă sau încercarea de a accesa un câmp de referință null va declanșa simultan o NullPointerException.

Dacă ați experimentat durerea NullPointerException(și nu avem noi toate la un moment dat?), atunci există veste bună: siguranța nulă este integrată în limba Kotlin. Compilatorul Kotlin nu vă permite să atribuiți o valoare nulă unei referințe de obiect, deoarece vă verifică în mod specific codul pentru prezența unor posibile obiecte nul în timpul compilării. Dacă compilatorul Kotlin detectează că a NullPointerException pot fi aruncate la runtime, atunci codul dvs. va eșua la timpul de compilare.

Modelul Kotlin de siguranță nulă înseamnă că (aproape) nu veți întâlni niciodată situații nul și NullPointerExceptions provenind din codul Kotlin. Singura excepție este dacă declanșezi a NullPointerException prin utilizarea incorectă a unuia dintre operatorii speciali Kotlin sau dacă utilizați unul din acești operatori pentru a declanșa în mod deliberat o NullPointerException (vom explora operatorii în mai multe detalii mai târziu în acest articol).

Nulitate în practică

În Kotlin, toate variabilele sunt considerate non-nullabile în mod implicit, așa că încercarea de a atribui o valoare nulă unei variabile va duce la o eroare de compilare. De exemplu, următoarele nu se vor compila:

var exemplu: String = null

Dacă doriți ca o variabilă să accepte o valoare nulă, atunci va trebui să marcați explicit acea variabilă ca fiind nullabilă. Acesta este exact opusul Java, unde fiecare obiect este considerat în mod implicit nul labil, ceea ce reprezintă o mare parte a motivului NullPointerExceptions sunt atât de comune în Java.

Dacă doriți să declarați explicit că o variabilă poate accepta o valoare nulă, atunci va trebui să adăugați o valoare ? la tipul de variabilă. De exemplu, următoarele voi compila:

var exemplu: String? = nul

Atunci când compilatorul vede acest tip de declarație, recunoaște că aceasta este o variabilă nullabilă și o va trata un pic diferit, mai ales vă împiedică să apelați o metodă sau să accesați o proprietate pe această referință nullabilă, ajutându-vă din nou să evitați acele plictisitoare NullPointerExceptions . De exemplu, următoarele nu se vor compila:

var exemplu: String? = null example.size

Deși designul lui Kotlin înseamnă că este dificil să întâlniți NullPointerExceptions provenind din codul Kotlin, dacă proiectul dvs. are un amestec de Kotlin și Java, atunci porțiunile Java ale proiectului dvs. pot fi în continuare o sursă de NullPointerExceptions.

Dacă lucrați cu un amestec de fișiere Kotlin și Java (sau poate aveți nevoie în mod specific să introduceți valori nul în codul dvs. Kotlin), atunci Kotlin include o serie de operații speciale care sunt proiectate să vă ajute să gestionați cu grație orice valori nula pe care le întâlniți.

1. Operatorul de apel în condiții de siguranță

Operatorul de apel în condiții de siguranță ?. vă oferă o modalitate de abordare a referințelor care ar putea să conțină o valoare nulă, asigurându-vă că orice apel la această referință nu va duce la o NullPointerException.

Când adăugați un operator de apel în condiții de siguranță la o referință, acea referință va fi testată pentru o valoare nulă. Dacă valoarea este nulă, atunci null este returnată, altfel referința obiectului va fi utilizată așa cum ați intenționat inițial. În timp ce ați putea obține același efect folosind un dacă , operatorul de apel în condiții de siguranță vă permite să efectuați aceeași lucrare cu mult mai puțin cod.

De exemplu, următoarele se vor întoarce a.size doar dacă A nu este null-altfel, va reveni null:

o? .size

Puteți, de asemenea, să lanțați împreună operatorii de telefonie de siguranță:

val number = person ?.adresa? .street? .number

Dacă oricare dintre expresiile din această serie este nulă, atunci rezultatul va fi nul, altfel rezultatul va fi valoarea solicitată.

2. Operatorul Elvis

Uneori veți avea o expresie care ar putea să conțină o valoare nulă, dar nu doriți să o aruncați NullPointerException chiar dacă această valoare face se dovedesc a fi nul.  

În aceste situații, puteți utiliza operatorul lui Elvis de la Kotlin ?: pentru a oferi o valoare alternativă care va fi utilizată ori de câte ori valoarea se dovedește a fi nulă, ceea ce reprezintă, de asemenea, o modalitate bună de a împiedica propagarea valorilor null în codul dvs..

Să examinăm un exemplu al operatorului Elvis în acțiune:

 fun nume setName (nume: String?) username = nume?: "N / A"

Aici, dacă valoarea este la stânga operatorului Elvis nu null, atunci valoarea părții din stânga este returnată (Nume). Dar dacă valoarea din stânga a operatorului Elvis este null atunci expresia din dreapta va fi returnată, ceea ce este în acest caz N / A.  

3. The !! Operator

Dacă doriți vreodată să vă forțați codul Kotlin să arunce un NullPointerException în stil Java, atunci puteți utiliza !! operator. De exemplu:

val numărul =

Aici, folosim !! operator pentru a afirma că Nume variabila nu este nulă. Atata timp cat Nume conține o referință validă, atunci numărul variabil este setat la lungime a șirului. Dacă Nume nu conține o referință valabilă, atunci Kotlin va arunca o NullPointerException.

Expresii Lambda

O expresie lambda reprezintă o funcție anonimă. Lambdas reprezintă o modalitate foarte bună de a reduce cantitatea de cod necesară pentru a efectua anumite sarcini care apar mereu în dezvoltarea Android - de exemplu, scrierea ascultătorilor și a apelurilor telefonice. 

Java 8 a introdus expresii native lambda, iar acestea sunt acum acceptate în Android Nougat. Deși această caracteristică nu este ceva unic pentru Kotlin, merită să ne uităm la ele. În plus, dacă lucrați la un proiect care conține atât codul Kotlin cât și codul Java, puteți utiliza acum expresii lambda în întregul dvs. proiect!

O expresie lambda cuprinde un set de parametri, un operator lambda (->) și un corp de funcție, aranjate în următorul format:

x: Int, y: Int -> x + y

Când construiți expresii lambda în Kotlin, trebuie să aveți în vedere următoarele reguli:

  • Expresia lambda ar trebui să fie înconjurată de acolade.

  • Dacă expresia conține parametri, atunci trebuie să le declarați înainte de -> arrow simbol.

  • Dacă lucrați cu mai mulți parametri, atunci trebuie să le separați prin virgule.

  • Corpul merge după -> semn.

Principalul beneficiu al expresiilor lambda este că vă permit să definiți funcții anonime și apoi să treceți imediat aceste funcții ca expresie. Acest lucru vă permite să efectuați mai multe sarcini comune de dezvoltare mai succintă decât ați putea în Java 7 și mai devreme, deoarece nu mai trebuie să scrieți specificația funcției într-o clasă abstractă sau într-o interfață. De fapt, lipsa de lambda în Java 7 și mai devreme este o mare parte din motivul pentru care ascultătorii de scriere și callback-urile au fost în mod tradițional atât de obosiți în Android.  

Să aruncăm o privire la un exemplu obișnuit: adăugarea unui buton de ascultare a unui clic. În Java 7 și mai devreme, acest lucru ar necesita de obicei următorul cod:

button.setOnClickListener (noul View.OnClickListener () @Override public void onClick (Vizualizare v) Toast.makeText (aceasta, "Buton clicked", Toast.LENGTH_LONG) .show (););

Cu toate acestea, funcțiile Kotlin lambda vă permit să setați un ascultător de clic utilizând o singură linie de cod:

buton.setOnClickListener (view -> toast ("Buton apăsat"))

Deja, este mult mai succint și mai ușor de citit, dar putem merge mai departe - dacă o funcție are o altă funcție ca ultimul parametru, atunci o puteți trece în afara listei de paranteze:

buton.setOnClickListener () toast ("Butonul apăsat")

Și dacă funcția are doar un parametru care este o funcție, puteți elimina complet parantezele:

buton.setOnClickListener toast ("Buton apăsat")

Funcții de extensie

Similar cu C #, Kotlin vă permite să adăugați noi funcționalități la clasele existente pe care altfel nu le-ați putea modifica. Deci, dacă credeți că o clasă lipsește o metodă utilă, atunci de ce nu o adăugați singură, prin intermediul unei funcții de extensie?

Creați o funcție de extindere prin prefixarea numelui clasei pe care doriți să o extindeți la numele funcției pe care o creați.

De exemplu:

distracție AppCompatActivity.toast (msg: String) Toast.makeText (aceasta, msg, Toast.LENGTH_LONG) .show ()

Rețineți că acest cuvântul cheie din interiorul funcției de extensie corespunde cu AppCompatActivity exemplu care .paine prajita este chemat.

În acest exemplu, trebuie doar să importați AppComptActivity și Paine prajita clase în tine .kt fișier și apoi sunteți gata să apelați . notație privind instanțele clasei extinse.

Când vine vorba de dezvoltarea Android, puteți găsi funcții de extensie deosebit de utile pentru a oferi ViewGroups capacitatea de a se umfla, de exemplu:

distracție ViewGroup.inflate (@LayoutRes layoutRes: Int, attachToRoot: Boolean = false): Vizualizați return LayoutInflater .from (context) .inflate (layoutRes, this, attachToRoot)

Deci, în loc de a scrie următoarele:

val view = LayoutInflater. de la (părinte) .inflate (R.layout.activity_main, parent, false)

Puteți utiliza pur și simplu funcția de extensie:

vizualizare val = parent.inflate (R.layout.activity_main)

Obiectele Singleton

În Java, crearea singletonilor a fost de obicei destul de verbose, necesitând să creați o clasă cu un constructor privat și apoi să creați acea instanță ca un atribut privat.

Rezultatul final este, de obicei, ceva de genul:

clasa publica Singleton privată statică Singleton singleton = new Singleton (); private Singleton ()  public static Singleton getInstance () return singleton;  

În loc de a declara o clasă, Kotlin vă permite să definiți un singur obiect, care este semantic la fel ca un singleton, într-o singură linie de cod:

obiect KotlinSingleton 

Apoi puteți folosi acest singleton imediat, de exemplu:

obiect KotlinSingleton fun myFunction () [...] KotlinSingleton.myFunction ()

Concluzie

În acest articol, am analizat în profunzime designul sigur al lui Kotlin și am văzut cum vă puteți asigura că proiectele Android rămân nesigure în siguranță, chiar dacă conțin o combinație de coduri Java și Kotlin utilizând o serie de operatori speciali. De asemenea, am aruncat o privire asupra modului în care puteți utiliza expresii lambda pentru a simplifica unele sarcini comune de dezvoltare în Android și cum să adăugați noi funcționalități la clasele existente.

În combinație cu ceea ce am învățat în Partea 1: Java vs. Kotlin și Partea 2: Începeți, aveți acum tot ce aveți nevoie pentru a începe să construiți aplicații Android eficiente folosind limbajul de programare Kotlin.

Distrează-te cu limbajul Kotlin și de ce nu verificați câteva dintre celelalte cursuri și tutoriale ale programului nostru de programare Android?

  • Înțelegerea concordanței pe Android utilizând HaMeR

    În acest tutorial vom explora cadrul HaMeR (Handler, Message and Runnable), unul dintre cele mai puternice modele de concurență disponibile pe Android. Tu o să ...
    Tin Megali
    Android SDK
  • Începeți cu Firebase pentru Android

    Crearea unui server back-end necesită un set de competențe pe care majoritatea dezvoltatorilor independenți de aplicații le lipsește. Din fericire, există Firebase, o platformă bazată pe cloud care ...
    Ashraff Hathibelagal
    Android SDK
  • Android de la zero: senzori hardware

    Unul dintre lucrurile care face ca dezvoltarea pentru dispozitive mobile să fie diferită de alte platforme este că un telefon mobil sau o tabletă este plină de senzori și ...
    Paul Trebilcox-Ruiz
    Android SDK
  • Faceți fotografii cu aplicația dvs. Android

    Magazinul Google Play are zeci de aplicații pentru camere - fiecare dintre ele permițând un alt mod de a face fotografii sau de a face ceva unic cu imaginile din ...
    Ashraff Hathibelagal
    Android SDK
Cod