Kotlinin käytön vaara.syntetic for block in layout

Photo by Justin Chrn on Unsplash

Nyt Kotlinin tulon myötä Androidin kehitykseen on ilmestynyt käyttökelpoinen työkalu, jonka avulla voidaan bindata näkymiä xml-layoutista luokkaan. Tämä on kotlinx.android.synthetic. Enää ei tarvitse käyttää metodia findViewById(). Riittää, että kirjoitat xml:ssä määritellyn id:n arvon, ja voit käyttää näkymää luokassa.Tästä on monia artikkeleita, kuten esimerkiksi virallinen kuvaus. Mutta voi olla ei-selviä ongelmia tagin <include> käyttämisessä layoutissa. Luodaan pieni esimerkki ja yritetään näyttää tällainen tapaus.

Testisovellus on lista, jossa on kaksi kohdetta, joista kumpikin sisältää painikkeen tekstillä. Aluksi luodaan layoutit kohteita varten – item1.xml ja item2.xml. Taustalla painikkeen takana on eri värit hyödyllisemmän näkyvyyden vuoksi.

Keskitytään siihen, että kohteiden painikkeilla on sama id ”button”. Se on tärkeä asia.

Seuraavaksi lisätään nuo itemit main_layoutiin apuna käyttäen <include> tagia:

Käytetään sitä nyt luokassa layoutina:

Ajetaan sovellus ja saadaan seuraava tulos:

Ongelman tunnistaminen

Tehdään nyt pieni ominaisuus, ja muutetaan painikkeiden tekstiä koodissa. Ensimmäiseen painikkeeseen tulee uusi teksti ”Changed Text First Item” ja toiseen painikkeeseen ”Changed Text Second Item”. Painikkeiden sitomiseen käytetään kotlinx.synthetic aliasilla:

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

On selvää, että button1 on näkymä item1.xml:stä, button2 item2.xml:stä. Seuraavaksi muutetaan teksti OnCreate:

Ajetaan sovellus ja katsotaan tulos:

Oops! Se ei ole sitä, mitä odotimme. Ensimmäisen painikkeen teksti muuttui tekstiksi, joka oli kirjoitettu toiselle painikkeelle, ja toisen painikkeen teksti ei muuttunut täysin.

Ongelman selitys

Yritetään ymmärtää, mikä on tämän tuloksen syy. Katso nyt, miten synteettinen työ toimii konepellin alla. Sitä varten dekompiloidaan Kotlin-luokka Javaksi (Show Kotlin Bytecode -> Decompile for AndroidStudio). Nyt MainActivity näyttää tältä:

Nyt voimme ymmärtää, miten synteettinen toimii. Aktiviteetissa on HashMap, joka käyttää avaimena näkymän id:tä ja arvona näkymäobjektia. Se täytetään laiskalla alustuksella. Meidän tapauksessamme ensimmäinen kutsu button1:lle etsii HashMapin arvoa avaimella id = R.id.button. Koska tällaista arvoa ei vielä ole, metodi lisää mapiin parin, jossa id on avaimena ja button-objekti item1:stä arvona. Tämän tuloksena ensimmäisen painikkeen tekstiä sovelletaan onnistuneesti.

Kutsu button2:een, jolla on myös id = R.id.button, tarkistaa tämän avaimen map-arvon, löytää ensimmäisen näkymämme (painike ensimmäisestä itemistä) ja täyttää sen toisen painikkeen arvolla. Tuloksena ensimmäinen painike vaihtaa tekstiä kahdesti, toinen ei kertaakaan

Ongelman ratkaisu

Aluksi voit käyttää eri id:tä jokaiselle näkymälle. Mutta jos siitä ei ole hyötyä, voit palata findViewById:

Ajetaan sovellus ja katsotaan tulos:

Nyt se toimii oikein!

Johtopäätös

Kielen uudet ominaisuudet antavat paljon hyötyä, mutta sinun pitäisi ymmärtää, miten se toimii ongelmien välttämiseksi.

Kiitos, että luit tämän artikkelin! Toivottavasti siitä on sinulle hyötyä

Jätä kommentti