Hlavní navigace

Mobilní čtečka článků: od obyčejného HTML k robustní nativní aplikaci

7. 10. 2020
Doba čtení: 7 minut

Sdílet

 Autor: Seznam.cz
Následující článek pojednává o tom, jakým způsobem se pracovalo s tělem článku v aplikaci Novinky.cz na Androidu dříve a jak je to v současnosti. Poskytne náhled do obou řešení a provede jejich srovnání.

Novinky.cz před rokem 2020

Ačkoliv se jedná o mobilní aplikaci, je třeba hned na úvod říct, že články v ní tak úplně nativní v této době nebyly. Detail článku v aplikaci byl hybrid, kde se nativní komponenty míchaly dohromady s různými html šablonami a obsahem zobrazovaným přes WebView. Pokud to mírně zjednodušíme, tak to vypadalo tak, že v horní části layoutu bylo ImageView (popřípadě video přehrávač) a pod ním WebView. Datově byly články relativně jednoduché, obsahovaly zejména titulek, perex, obsah, url titulní fotky atd. Nejzajímavější je právě onen obsah.

Nejednalo se vlastně o nic jiného, než html, které samozřejmě mohlo obsahovat obrázky, odkazy, videa a další prvky, které byly součástí článku. Nicméně z hlediska aplikace nebylo chtěné a dost dobře ani smysluplně možné jakkoliv tento obsah upravovat, rozdělit na jednotlivé části atd. Pro potřeby mobilní aplikace vznikla šablona, kam se dosazoval titulek, perex, datum aktualizace a potom celý obsah článku.

Nejspíš jediná výhoda tohoto přístupu byla vcelku rychlá implementace, protože stačilo vzít html obsah, který aplikace dostala z backendu, dosadit do jednoduché šablony a vložit do WebView. Co se vizuálních úprav týče, byly řešené pomocí několika CSS stylů natvrdo vložených v aplikaci, z nichž se dalo vybrat. Pár dalších maličkých úprav jako handling prokliknutých odkazů a je hotovo, uživatel může číst článek. Celý layout pro obrazovku s článkem se tedy dal sestavit z počtu UI komponent, které by se daly spočítat na prstech jedné ruky.

Tento přístup je z dnešního pohledu nevýhodný hned z několika důvodů. Html je z nativního hlediska aplikace velice nepříjemný a na zpracování obtížný formát, tudíž není jednoduché např. řešit změny velikosti obrázků, prokliky jednotlivých částí textu, převod textu na řeč, implementovat uživatelsky přívětivé přehrávání videa atd.

Další nevýhodou je to, že článek je závislý např. na aktuální verzi WebView v aplikaci, jednotlivé části článku se nerecyklují, některé části článku pro mobilní aplikaci musely být vynechávány, protože nefungovaly úplně správně a stávalo se, že u delších článků načítání trvalo neúměrně dlouhou dobu. Samostatnou kapitolou je prakticky nemožnost injektovat na různá místa v článku další dynamický obsah (např. reklamu). Celkově práce s obsahem článku tady je velmi nepříjemná a klade na programátora nutnost znalosti webových technologií jako html a css, což nemusí být u mobilního vývojáře samozřejmost.

Novinky.cz v roce 2020

V současné verzi aplikace už je článek řešen zcela jiným způsobem a to (téměř) úplně nativně. To by samozřejmě nebylo možné bez změny datové struktury. V současné době už obsah není jedno velké html, ale článek je rozdělen do samostatných částí (tzv. molekul), se kterými se dá pracovat jednotlivě. Příklady těchto molekul jsou obrázek, video, odstavec, odkaz, galerie, mapa atd.

Nezávislé molekuly už nejsou reprezentovány jako html, ale aplikace je dostává ve formě mnohem lépe parsovatelného JSONu. Díky tomu je možné článek vykreslovat místo ve WebView pomocí RecyclerView, přičemž každá z molekul reprezentuje samostatnou, přizpůsobitelnou a plně recyklovatelnou (i když ne vždy chceme vše recyklovat) položku.

Na první pohled zřejmá výhoda tohoto přístupu je rychlost vykreslování, protože se reálně naplňují jen ty buňky, které jsou právě vidět. Nejvýraznější posun v performance je zejména u komplexnějších článků. Také je možné jednoduše upravovat formát jakéhokoliv obrázku, přímo v textu přehrávat videa, měnit velikost písma či barevné schéma, nebo libovolně reagovat na proklik jakékoli komponenty článku.

U jednotlivých částí, už také přesně víme, co je text a nemáme tam již různé řídicí html znaky jako dříve. To umožňuje aplikovat převod textu na řeč (Text-to-Speech) a současná verze aplikace tedy umožňuje uživatelům nechat si článek přečíst. Každá z molekul je reprezentována vlastní modelovou třídou, má přiřazený vlastní layout a vlastní ViewHolder, přičemž bind metoda tohoto ViewHolderu bere jako parametr právě modelovou třídu dané molekuly.

Aby bylo možné zajistit správnou implementaci pokročilejších funkcí aplikace, každý z modelů molekul je implementací rozličného počtu rozhraní. Velmi častým příkladem, který se vyskytuje u většiny molekul je rozhraní umožňující funkci Text-to-Speech, které nutí danou molekulu specifikovat, které její části se budou převádět na řeč a jakým způsobem. 

Toto rozhraní se nachází obecně u všech modelů, které obsahují nějaký text, naopak chybí u obrázků, videí atd. Možná ještě zajímavějším případem rozšířeným mezi více molekul je rozhraní umožňující práci s videem (ta by sama o sobě stačila nejspíš na celý článek). Zjednodušeně řečeno jde o implementace metod, které definují, jakým způsobem videa přecházejí do režimu celé obrazovky, jak mezi sebou interaguje více instancí videopřehrávače, kdy se videopřehrávač zmenší a přepne do tzv. sticky režimu nebo kdy a za jakých podmínek se tyto instance uvolňují z paměti.

ViewHoldery obsahující video jsou specifické také v tom, že se ne vždy plně recyklují. To kvůli tomu, že plná inicializace nebo obnovování stavu přehrávače je ve většině případů dražší a náročnější, než uchovávání vícero instancí ViewHolderu s přehrávačem najednou (podobný případ jsou některé ViewHoldery zobrazující obsah vložený od třetích stran). 

Další příklady rozhraní, které některé molekuly implementují jsou přechody do galerie, zobrazení webového obsahu nebo specifikace reakcí na změnu velikosti písma. Poslední zvláštností, kterou stojí za to zmínit a která vnáší zajímavý rekurzní prvek jsou molekuly, které mohou obsahovat jiné molekuly a tím vytvářejí nějaké logicky i vizuálně související celky, které ale jsou stále reprezentovány samostatně.

Celý článek potom funguje tak, že adaptér, který je nasazený do RecyclerView dostává skrze LiveData kolekci modelů molekul, vytváří a bindují se příslušné ViewHoldery a v případě, že je potřeba vizuálně něco změnit, tak se pomocí payloadu pouze updatují příslušné ViewHoldery bez nutnosti překreslovat celý článek.

RecyclerView také používá vlastní LayoutManager, který zajišťuje bindování ViewHolderů s dostatečným předstihem tak, aby i při rychlém pohybu v článku s komplexnějším obsahem nedocházelo k zásekům. Důležitou funkcí je také ukládání článků pro offline konzumaci, kdy stačí uložit příslušný JSON a soubory pro média, z čehož pak lze celý článek jednoduše rekonstruovat.

Bohužel není možné se úplně zbavit strašáka v podobě WebView a to kvůli obsahu třetích stran, který se do článku někdy vkládá. Ať už jde o příspěvky z Twitteru, Facebooku nebo třeba o video na YouTube, které se článkem souvisí. V těchto případech má WebView stále své uplatnění. Už to zdaleka není ve všech případech, nicméně stále jde o poměrně komplexní problematiku, kdy je potřeba řešit spoustu na první pohled ne zcela zřejmých problémů jako třeba interakce videa vloženého z YouTube a vlastního videa, které je součástí článku tak, aby nedocházelo k situacím, že se uživateli spustí například více videí najednou.

Celý systém je řešen tak, aby byl jednoduše modifikovatelný a flexibilní, protože se počítá s tím, že bude využit i v jiných aplikacích, které nějakým způsobem zobrazují články. Pomocí factory patternu je možné overridovat např. layouty pro jednotlivé molekuly nebo implementace jednotlivých rozhraní a tím ohýbat všechny výše popsané funkce.

Oproti původnímu přístupu pomocí WebView je asi jedinou nevýhodou současného řešení daleko náročnější implementace. V aplikaci Novinek je v současné chvíli používáno 23 různých molekul, přičemž ke každé náleží minimálně jedna modelová třída, jeden ViewHolder a jeden layout. Dále je potřeba relativně složitý adaptér, LayoutManager, vlastní scroll handler na RecyclerView a další podpůrné třídy. To všechno místo jedné html šablony, jednoho modelu a jednoho layoutu. To značně rozšiřuje codebase a zvyšuje komplexitu aplikace.

Etický hacking

Uživatelé jsou náročnější

Nároky uživatelů na mobilní aplikaci v roce 2020 jsou diametrálně odlišné, než byly při původním vydání aplikace Novinek v roce 2011. Tehdy řešení článku jako jednolitého html obsahu bylo nejspíše správnou volbou i s ohledem na backend aplikace. V současné době jsou už kromě samotného zobrazení těla článku vyžadovány různé druhy interakce – tmavý režim, změny velikosti písma, převod textu na řeč, otevření galerie proklikem obrázku, přechod na jiný článek přes pouták, různé animace, ukládání pro offline konzumaci atd. 

Přechod na nový způsob reprezentace a zobrazování článku umožňují přesně tyto interakce uživatelům nabízet a zlepšovat tak jejich zážitek z používání aplikace. Kromě toho je systém výrazně flexibilnější, jelikož umožňuje modifikace jednotlivých částí. Je i robustnější, protože pokud nastane nějaká chyba, může např. z článku vypadnout odkaz nebo obrázek, ale článek jako celek funguje dál. Rozhodně plánujeme tento přístup používat i v dalších obsahových aplikacích.

Autor článku

Pracuje jako vedoucí vývojového týmu ve společnosti Seznam.cz. Zabývá se vývojem aplikací pro Android.