findViewById vs. View Binding - zizanek/-github-tz-pma-2026-priprava GitHub Wiki

Propojení XML layoutu s Kotlinem: findViewById vs. View Binding

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.


1. Starší přístup: findViewById

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>).

Příklad zápisu:

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()
        }
    }
}

Nevýhody findViewById:

  • 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 findViewById vrátí null. Následné použití takové reference může způsobit pád aplikace s chybou NullPointerException.
  • 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 na ClassCastException.
  • 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ý.

2. Moderní přístup: View Binding

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řídu ActivityMainBinding
  • item_bike.xml ➔ vygeneruje třídu ItemBikeBinding

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.


3. Postup aktivace View Bindingu v projektu

Krok 1: Povolení v build.gradle.kts (Module :app)

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.


Krok 2: Použití v MainActivity.kt

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()
        }
    }
}

Co znamená odložená inicializace (lateinit var)

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 MainActivity je vytvářena samotným systémem ještě předtím, než je připraveno grafické rozhraní aplikace.
  • Objekt binding se obvykle vytváří až uvnitř metody životního cyklu onCreate(), kde se připravuje uživatelské rozhraní aktivity. Pomocný objekt layoutInflater, který slouží k vytvoření ActivityMainBinding, však není dostupný výhradně v metodě onCreate().
  • Proměnnou binding deklarujeme na úrovni třídy (jako členskou vlastnost), pokud k ní chceme přistupovat nejen v onCreate(), 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á a lateinit není nutný.

Klíčové slovo lateinit (zkratka pro late initialization – pozdní/odložená inicializace) říká překladači Kotlinu:

  1. „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.“
  2. Umožňuje vyhnout se neustálému ověřování na hodnotu null (binding?. nebo binding!!) v celém dalším kódu.
  3. 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ýjimku UninitializedPropertyAccessException.

4. Porovnání obou přístupů

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.

5. Shrnutí pro výuku

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.

⚠️ **GitHub.com Fallback** ⚠️