Úvod do knihovny Anko pro Android (2/4) | eMan

Úvod do knihovny Anko pro Android (2/4)

Ukážeme si pár triků, jak si usnadnit práci s toasty a dialogy. Čeká nás taky spouštění aktivit a dostaneme se i k dalším užitečným vychytávkám, co můžeme v knihovně Anko najít. Tento článek navazuje na první díl, kde jsme položili základy, na kterých teď budeme stavět naši demo aplikaci.

V prvním článku jsme si vytvořili Kotlin Android projekt v Android Studiu 3. Taky jsme si ukázali základní použití knihovny Anko a udělali jsme první View, které jsme definovali v samostatné komponentě (AnkoComponent).

V tomto v pořadí druhém článku budeme pokračovat s rozvíjením znalostí o této úžasné knihovně pro vývoj Android aplikací. Dozvíme se například:

  • Jak jednodušeji zobrazit toasty a dialogy
  • Jak spustit aktivitu
  • Jaké další užitečné funkce Anko obsahuje, například spuštění věcí na pozadí nebo v UI vlákně

Přehled dílů série:

1. Vytvoření projektu v Android Studio 3 a první UI
2. Tlačítka, toasty, dialogy, intenty, uživatelská rozhraní a práce na pozadí (background threads)
3. Vylepšujeme naše UI
4. Fragmenty

 

Tlačítko onClick a Toast widget

V této části si ukážeme, jak můžeme v Anko zaregistrovat onClick akci k tlačítku, číst uživatelem zadaný text v EditText komponentě a zobrazovat toasty.

Vraťme se k našemu SignInView, které jsme vytvořili v minulém díle. Díky Kotlinu, a hlavně Anko knihovně, už nemůže být přidání onClick akce jednodušší:

Pokud však budeme vytvářet UI za pomocí Anko DSL (přímo v kódu namísto v XML), pak náš kód může vypadat ještě mnohem lépe:

Jak jste si mohli všimnout, pro každý ze dvou případů jsme použili jiné definování zobrazení toast komponenty. V prvním případě zobrazujeme toast klasickým Android způsobem. V druhém případě jsme už využili extension funkci z Anko knihovny pro zobrazení toastu. Tím pádem se vyhneme časté chybě, tedy tomu, že zapomeneme zavolat metodu show(). V obou případech se nám tak zobrazí toast s časovým zobrazením nastaveným na “SHORT”. Pokud chcete zobrazit “LONG” toast, pak Anko nabízí extension funkci s celkem logickým názvem:

Nyní se zaměříme na EditText pro zadávání username. Po stisknutí tlačítka Sign In zobrazíme toast obsahující text, který uživatel zadal do pole username.

Nejdříve musíme získat referenci na username:

Poté můžeme přidat onClick DSL blok do Sign In tlačítka a zobrazit text v daném toastu:

Prozatím máme kód hotový, tak si spustíme aplikaci a otestujeme si to. Jestli jste všechno udělali správně, uvidíte něco jako na následujícím obrázku (za předpokladu, že jste zadali text Anko):

Jen pro kontrolu, váš kód v SignInView.kt by měl vypadat takto:

 

Vytvoření Sign In Business logiky

Teď budeme vyvářet první business logiku v rámci série článků o knihovně Anko. Nejdřív si ale připravíme doménové objekty.

Pro náš zatím jediný proces Sign In vytvoříme nový Kotlin soubor a pojmenujeme si ho jako DomainObjects.kt. Tam budeme definovat všechny naše POJO objekty jako datové třídy (data class). Tento soubor umístíme do nového package pojmenovaného jako model (v sign_in package). Následně v tomto souboru vytvoříme první datovou třídu pod názvem AuthCredentials s těmito argumenty:

Vytvoříme další package bl (jako business logic, případně si ho pojmenujte, jak uznáte za vhodné), nové rozhraní ISignInBL.kt a jeho implementaci SignInBL.kt.

V ISignInBL.kt rozhraní nadefinujeme funkci checkUserCredentials:

Následně tuto funkci nadefinujeme v SignInBL.kt, kde provedeme kontrolu uživatelského jména a hesla. Pro náš demo projekt nebudeme implementovat žádnou perzistentní vrstvu (to si ukážeme v budoucích článcích o Kotlinu, respektive o knihovně Requery). Kontrolu proto provedeme tak, že uživatel bude puštěn dál, pokud zadá uživatelské jméno = frosty a heslo = snowman.

Super, máme připravenou velice jednoduchou business logiku pro sing in proces. V dalším kroku musíme přidat získání zadané hodnoty z username a password edit textů a jejich kontrolu. Ta se bude hodit v případě, že uživatel naší aplikace kolonky nevyplní. Poté využijeme business logiku pro kontrolu uživatelského přístupu (voláním checkUserCredentials funkce).

Kontrola v Sign In formuláři

Jak jsme si už řekli, budeme přidávat kontrolu vstupních polí (username a password) v Sign In formuláři. Jako první na seznamu je získání reference na námi vytvořené EditText komponenty (to samé jsme udělali v úvodu článku pro username):

Následně vytvoříme privátní funkci handleOnSignInButtonPressed s těmito argumenty:

  • ui: AnkoContext
  • username: String
  • password: String

Tou nahradíme náš “Hello” toast (onClick DSL blok přidaný k Sign In tlačítku):

 

Alert Dialog

Anko obsahuje DSL blok pro zobrazování dialogů:

Celkem jednoduché, co říkáte?

Už víme, jak v Anko zobrazit Alert dialog. Nic nám tedy nebrání si nově nabytou znalost vyzkoušet v naší demo aplikaci. Kód pro zobrazení dialogu umístíme do funkce handleOnSignInButtonPressed, kde zkontrolujeme správnost zadaných uživatelských dat, jinak řečeno zjistíme, jestli jsou uživatelem kolonky vyplněné:

Pokud jste zkoumali daný kód podrobněji, pak jste si určitě všimli, že používáme funkci isBlank(). Tato funkce se nachází ve stdlib Kotlin knihovny a slouží ke kontrole. Díky ní se dozvíme, jestli je daný text prázdný, nebo jestli obsahuje bílé znaky. Taky jsme použili výraz with{}, kam jsme umístili definici Alert dialogu. Argument ui používáme proto, že definujeme UI v Anko komponentě a potřebujeme mít referenci na context této komponenty, abychom mohli využívat extension funkce z Anko.

Spustíme aplikaci a vyzkoušíme náš nový dialog. Ten by se měl zobrazit, pokud uživatel nevyplnil username nebo password a přesto stiskl Sign In tlačítko:

Málem bych zapomněl ještě ukázat definici nových textových řetězců:

 

Zobrazujeme aktivity, fragmenty z Anko komponenty

Předpokládám, že většina z vás v reálných aplikacích pro oddělení logiky od definice UI z aktivit či fragmentů používá MVP nebo něco podobného, případně už nové Architecture Components představené na Google I/O 17. V naší demo aplikaci nic z toho používat nebudeme. Pokud by vás ale zajímal jeden z MVP frameworků, který se jmenuje Mosby, můžete se podívat na můj projekt na githubu, kotlin-anko-demo, kde jsem zkoušel spojit Kotlin, Anko, Mosby a další knihovny.

Pro komunikaci mezi aktivitami, fragmenty a dalšími komponentami používám na reálných projektech RxJava & RxKotlin například implementací RxBus. V našem demu však budeme používat komunikaci mezi aktivitou a UI skrze volání Anko komponenty z příslušné aktivity.

Jak víte z prvního článku, když vytváříme AnkoComponent<T>, musíme definovat generický typ T jakožto vlastníka té dané komponenty. Díky tomu můžeme z komponenty přistupovat k aktivitě, která je s komponentou svázaná, tedy owner. Z komponenty SignInView se tak na aktivitu dostaneme voláním třeba ui.owner.someFunction(...).

Otevřete si třídu SignInActivity.kt a přidejte novou funkci authorizeUser:

Vraťme se zpět do SignInView.kt, kde jsme nechali TODO v else větvi z předešlé implementace. Uvnitř funkce handleOnSignInButtonPressed zavoláme nově vytvořenou funkci authorizeUser:

Teď se vrátíme zpátky do SignInActivity.kt, kde si ukážeme, jak využitím Anko knihovny můžeme jednoduše spustit kód na pozadí (background vlákno).

 

Asynchronní volání

Každý z vás jistě ví, jaké je to peklo používat AsyncTask v Androidu. Nebo je potřeba napsat hodně omáčky okolo. Anko knihovna nabízí velmi jednoduchý způsob, jak spustit operaci na pozadí:

Poznámka: Ukázky se vztahují k verzi 0.9, v novějších verzích knihovny můžeme používat Kotlin Courotines, ale o nich budu mluvit třeba někdy jindy.

Pokud potřebujete asynchronně zavolat jinou funkci, pak má Anko funkci doAsyncResult(function_call_here):

Dokonce můžete použít vlastní instanci exekutoru pro vykonání operace na pozadí:

Víme o další skvělé části knihovny Anko, tak si ji pojďme vyzkoušet.

V SignInActivity kontrolujeme správnost uživatelského jména a hesla zadaného uživatelem v Sign In formuláři. V reálné aplikaci bychom měli tyto údaje uložené například v databázi, ale tou se v tomto článku zabývat nebudeme. Anko samozřejmě obsahuje řadu extension metod pro práci s SQLite, ale o tom třeba jindy. Kontrolu správnosti uživatele provedeme v background vlákně (asynchronně):

Co vlastně v tomto kódu děláme? Na pozadí provádíme kontrolu uživatelských dat voláním příslušné funkce, kterou jsme definovali v business logice. Výsledek kontroly pak zpracováváme v UI vlákně aktivity. Pokud je vše v pořádku, zobrazíme toast, jinak se zobrazí alert dialog.

Poznámka: uiThread() volání se v Anko chová trošku odlišně, podle toho, jestli voláte například z aktivity. V tom případě se kód v lambdě nevykoná, pokud metoda isFinishing() na dané metodě vrací true. Pokud si to ale v aktivitě z nějakého důvodu přejete obejít, pak můžete použít kontext a zavolat na něm ctx.uiThread { }.

Aktuální kód SignInActivity by měl být:

V dalším kroku se vrátíme k SignInView.kt, tady nám totiž chybí implementovat funkci showAccessDeniedAlertDialog, kterou jsme v předchozím kroku přidali do aktivity:

V metodě používám proměnnou ankoContext, ale kde se vzala? Jedná se o globální proměnnou s definicí Anko kontextu (předtím ui: AnkoContext<SignInActivity>), tak, abychom k ní měli přistup i z dalších funkcí:

 

Intenty

V této kapitole bych vám rád ukázal, jak můžeme využít Anko knihovnu pro práci s intenty.

Pokud se podíváte do zdrojových kódů Anko knihovny, tak tyto funkce nejsou nic jiného než extension funkce:

Extension funkce z Anko můžeme použít pro práci s intenty, tak si to pojďme hned vyzkoušet v našem demo projektu. Takže jak spustit SignInActivity z MainActivity třídy?

Pokud nepotřebujeme při startu aktivity zadat žádné flagy či parametry, můžeme jednoduše napsat:

Pokud ale potřebujeme nastavit parametry, pak by náš kód bez použití Anko knihovny vypadal takto:

Využitím extension funkcí z Anko knihovny můžeme tento kód upravit:

V naší demo aplikaci ale žádné argumenty či flagy nastavovat nebudeme, takže náš výsledný kód pro MainActivity je následující:

 

Shrnutí 2. části

V tomto druhém díle ze série o knihovně Anko jsme si řekli, jak jednodušeji zobrazovat na Androidu toasty a dialogy. Ukázali jsme si, jak definovat různé akce/action listenery pro UI komponenty. V našem případě to byla onClick akce přidaná na Sign In tlačítko.

Dále jsme zkusili interakci mezi AnkoComponent (SignInView) a aktivitou a asynchronní volání a spuštění operací na pozadí.

V příštím článku, tentokrát s pořadovým číslem tři, se vrátíme k UI a budeme si hrát s jeho vylepšením.

Václav Souhrada
Kotlin & Android Developer at eMan, Czech Kotlin User Group Founder and Organizer

Sledujte nás

Kontakt

+420 222 202 222
info@eman.cz

Sídlo a hlavní kancelář:
U Pergamenky 1145/12
170 00 Praha 7

Pobočka Hradec Králové:
Šimkova 1224/2B
500 03 Hradec Králové

Pobočka Plzeň:
Teslova 1266/7
301 00 Plzeň

Pobočka Mladá Boleslav:
Palackého 267
293 01 Mladá Boleslav

Sdíleno