findViewById vs. View Binding - zizanek/-github-tz-pma-2026-priprava GitHub Wiki
Při tvorbě uživatelského rozhraní pomocí XML layoutů existují dva základní způsoby, jak přistupovat k vizuálním prvkům (tlačítkům, textovým polím apod.) z kódu v jazyce Kotlin: starší přístup pomocí findViewById a moderní doporučený přístup pomocí View Binding.
Při tomto přístupu je nutné každý prvek z XML vyhledat v hierarchii zobrazení ručně podle jeho identifikačního názvu (R.id.<nazev>).
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Každý prvek se musí ručně vyhledat se zadáním jeho typu
val textTitle = findViewById<TextView>(R.id.textTitle)
val editGuess = findViewById<EditText>(R.id.editGuess)
val btnSubmit = findViewById<Button>(R.id.btnSubmit)
btnSubmit.setOnClickListener {
textTitle.text = editGuess.text.toString()
}
}
}-
Riziko pádu aplikace (Null Safety): Pokud je zadáno ID, které v projektu vůbec neexistuje, kód se nezkompiluje. Pokud však ID existuje, ale příslušný prvek není v aktuálně načteném layoutu, metoda
findViewByIdvrátínull. Následné použití takové reference může způsobit pád aplikace s chybouNullPointerException. -
Typová nebezpečnost (Type Safety): Pokud je v kódu uveden nesprávný typ (např.
findViewById<Button>(R.id.textTitle)u textového pole), kód se zkompiluje, ale aplikace spadne za běhu naClassCastException. - Nepřehlednost a opakující se kód: Při desítkách prvků na obrazovce vznikají desítky řádků opakujícího se kódu („boilerplate“). Metoda navíc vyhledává prvek v hierarchii pohledů, ale při běžném použití nemusí být rozdíl ve výkonu významný.
View Binding je nástroj, který pro každý XML layout automaticky vygeneruje odpovídající vazební třídu (tzv. binding class), pokud není daný layout z generování výslovně vyloučen.
Název této třídy vznikne převedením názvu XML souboru do velbloudí notace s příponou Binding:
-
activity_main.xml➔ vygeneruje tříduActivityMainBinding -
item_bike.xml➔ vygeneruje tříduItemBikeBinding
Všechny prvky, které mají v XML přiřazené android:id, jsou v této třídě přímo dostupné jako silně typované vlastnosti.
Uvnitř konfiguračního bloku android { ... } se zapne funkce viewBinding:
android {
// Ostatní nastavení projektu
buildFeatures {
viewBinding = true
}
}Po úpravě souboru se provede synchronizace kliknutím na Sync Now v horní části editoru.
class MainActivity : AppCompatActivity() {
// 1. Deklarace binding objektu s odloženou inicializací
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 2. Nafouknutí (inflate) layoutu do binding instance
binding = ActivityMainBinding.inflate(layoutInflater)
// 3. Nastavení kořenového pohledu (root) do okna aktivity
setContentView(binding.root)
// 4. Přímý a bezpečný přístup k prvkům přes 'binding.<id>'
binding.btnSubmit.setOnClickListener {
binding.textTitle.text = binding.editGuess.text.toString()
}
}
}V jazyce Kotlin musí mít běžná vlastnost na úrovni třídy přiřazenou výchozí hodnotu, být inicializována v konstruktoru, nebo musí být její inicializace vyřešena jiným podporovaným způsobem. Jednou z možností je povolit hodnotu null, např. var binding: ActivityMainBinding? = null.
U aktivit v Androidu však nastává specifická situace:
- Instance třídy
MainActivityje vytvářena samotným systémem ještě předtím, než je připraveno grafické rozhraní aplikace. - Objekt
bindingse obvykle vytváří až uvnitř metody životního cykluonCreate(), kde se připravuje uživatelské rozhraní aktivity. Pomocný objektlayoutInflater, který slouží k vytvořeníActivityMainBinding, však není dostupný výhradně v metoděonCreate(). - Proměnnou
bindingdeklarujeme na úrovni třídy (jako členskou vlastnost), pokud k ní chceme přistupovat nejen vonCreate(), ale také v dalších metodách či obsluze událostí. Pokud ji potřebujeme pouze uvnitřonCreate(), může být deklarována jako lokální proměnná alateinitnení nutný.
Klíčové slovo lateinit (zkratka pro late initialization – pozdní/odložená inicializace) říká překladači Kotlinu:
- „Tato proměnná v okamžiku vzniku třídy ještě nemá hodnotu, ale slibuji, že jí platnou hodnotu přiřadím dříve, než ji kdekoli poprvé použiji.“
- Umožňuje vyhnout se neustálému ověřování na hodnotu null (
binding?.nebobinding!!) v celém dalším kódu. - Pokud by byla hodnota z proměnné čtena před jejím přiřazením v
onCreate(), aplikace selže na jasně definovanou výjimkuUninitializedPropertyAccessException.
| Vlastnost | findViewById |
View Binding |
|---|---|---|
| Způsob získání reference | Ruční volání funkce pro každý prvek zvlášť. | Automaticky generované vlastnosti přes objekt binding. |
| Typová bezpečnost (Type Safety) |
Ne – hrozí pád při záměně typu (Button místo TextView). |
Ano – typ prvku je určen z XML v době kompilace. |
| Bezpečnost proti pádu (Null Safety) |
Nižší – pokud ID existuje, ale prvek není v aktuálním layoutu, metoda vrátí null a následné použití může způsobit pád aplikace. |
Vyšší – pokud ID v layoutu neexistuje, přístup k němu se obvykle nezkompiluje. U některých variant layoutu však může být vygenerovaná reference nullable. |
| Rychlost sestavení projektu | Nevyžaduje generování vazebních tříd. | Obvykle malý dopad na délku sestavování (generují se vazební třídy). |
| Množství kódu (Boilerplate) | Velké – desítky řádků definic proměnných. | Malé – stačí pouze inicializace objektu binding. |
Pro začátečníky je vhodné začít ukázkou findViewById, na které lze jednoduše vysvětlit samotnou podstatu propojování XML rozhraní s logickým kódem.
Jakmile jsou základy pochopeny, je doporučeno přejít na View Binding, protože eliminuje časté překlepy v názvech ID a představuje doporučený moderní způsob přístupu k prvkům XML layoutů v Androidu.
Poznámka: View Binding se používá při tvorbě uživatelského rozhraní pomocí XML layoutů. Při použití moderního deklarativního přístupu Jetpack Compose není View Binding potřeba, protože uživatelské rozhraní se vytváří přímo v Kotlinu.