Nebezpečí používání kotlinu.syntetic for block in layout

Foto: Justin Chrn na Unsplash

S příchodem jazyka Kotlin do vývoje pro Android se nyní objevil užitečný nástroj pro vazbu pohledů z xml-layout na třídy. Jedná se o kotlinx.android.synthetic. Není již třeba používat metodu findViewById(). Stačí zapsat hodnotu id, která je uvedena v xml, a můžete použít pohled ve třídě. existuje o tom mnoho článků, jako například oficiální popis. S použitím tagu <include> v layoutu však mohou nastat nezjevné problémy. Vytvoříme si malý příklad a pokusíme se takový případ ukázat.

Testovací aplikace je seznam se dvěma položkami, z nichž každá obsahuje tlačítko s textem. Nejprve vytvoříme rozvržení pro položky – item1.xml a item2.xml. Pozadí za tlačítkem má různé barvy pro užitečnější viditelnost.

Soustředíme se na to, aby tlačítka v položkách měla stejné id „button“. Je to důležitá věc.

Dále přidáme tyto položky do main_layout pomocí značky <include>:

Nyní je použijeme ve třídě jako layout:

Spustíme aplikaci a dostaneme následující výsledek:

Identifikace problému

Nyní provedeme malou funkci a změníme text tlačítek v kódu. U prvního tlačítka bude nový text „Změněný text první položka“ a u druhého tlačítka „Změněný text druhá položka“. Pro vazbu na tlačítka použijeme kotlinx.synthetic s aliasem:

import kotlinx.android.synthetic.main.item1.button as button1
import kotlinx.android.synthetic.main.item2.button as button2

Je zřejmé, že tlačítko1 je pohled z item1.xml, tlačítko2 z item2.xml. Dále změňte text na OnCreate:

Spustíme aplikaci a podíváme se na výsledek:

Oops! Není to to, co jsme očekávali. Text prvního tlačítka se změnil na text, který byl napsán pro druhé tlačítko, a text druhého tlačítka se absolutně nezměnil.

Vysvětlení problému

Pokusíme se pochopit, co je příčinou tohoto výsledku. Nyní se podívejte, jak funguje syntetická práce pod kapotou. Za tím účelem dekompilujte třídu kotlin do Javy (Show Kotlin Bytecode -> Decompile for AndroidStudio). Nyní MainActivity vypadá takto:

Nyní můžeme pochopit, jak syntetika funguje. Aktivita má HashMap, která používá id pohledu jako klíč a view-objekt jako hodnotu. Je naplněna línou inicializací. V našem případě první volání button1 hledá hodnotu HashMap podle klíče id = R.id.button. Protože taková hodnota zatím neexistuje, přidá metoda do mapy dvojici, kde je id jako klíč a button-objekt z položky1 jako hodnota. Výsledkem je úspěšné použití textu pro první tlačítko.

Volání tlačítka2, které má také id = R.id.button, zkontroluje hodnotu mapy pro tento klíč, najde naše první View (tlačítko z první položky) a vyplní ho hodnotou pro druhé tlačítko. Výsledkem je, že první tlačítko změní text dvakrát, druhé ani jednou

Řešení problému

Jako první můžete pro každé zobrazení použít jiné id. Ale pokud to není užitečné, můžete se vrátit k findViewById:

Spustíme aplikaci a podíváme se na výsledek:

Teď to funguje správně!

Závěr

Nové funkce jazyka dávají lof ot užitečné, ale měli byste pochopit, jak to funguje, abyste se vyhnuli problémům.

Díky za přečtení tohoto článku! Doufám, že pro vás bude užitečný

Napsat komentář