Router — az útválasztási minta alapjai iOS-ben és Androidban

Szerző: IT Sectr Megjelenés: 2026-02-19 Olvasási idő: 9 perc

Router (útválasztó) — architekturális minta, amely központosítja a navigációs logikát az alkalmazás képernyői között. A Router meghatározza, hová és hogyan kell navigálni egy esemény bekövetkeztekor. iOS-ben a Router absztrahálja az UINavigationController-t és a segue-t, Androidban — a FragmentManager-t és a NavController-t a Jetpack Navigation-ből. A Router működhet önálló mintaként vagy Coordinator (Router-per-Coordinator) és VIPER (Router-per-module) komponenseként. Bővebben — a Android Navigation Component Guide-ban.

Főbb pontok

  • Router — útválasztási minta, amely központosítja a képernyők közötti navigációt
  • Két szint — A Router lehet Coordinator komponens vagy önálló minta
  • iOS Router — absztrakció az UINavigationController felett push/present/pop metódusokkal
  • Android Router — Jetpack Navigation Component NavController-rel és deep link-ekkel
  • URL Routing — útválasztás URL-sémák alapján (deeplink, universal link)

Mi az a Router: az útválasztási minta lényege

Router — minta, amely beágyazza a képernyők közötti átmenet logikáját. Fő ötlet: a ViewController (vagy Presenter/ViewModel) nem közvetlenül hívja a navigationController.pushViewController-t, hanem értesíti a Router-t a navigációs szándékról. A Router dönti el, melyik ViewController-t hozza létre és hogyan jelenítse meg. A Router lehet egyszerű (navigációs metódusok gyűjteménye) vagy összetett (URL-sémák, deep link-ek és push értesítések szerinti útválasztással).

Három megközelítés a Router-hez — Router szolgáltatásként (globális Navigator-szingleton), Router modulkomponensként (VIPER megközelítés), Router protokollként (absztrakció a Coordinator számára). Globális Router — egyszerűség (egy példány alkalmazásonként) — népszerű kis projektekben. Moduláris Router — minden funkciónak saját Router-e van — a VIPER és Clean Architecture szabványa. Protokoll Router — Coordinator-ban használva: RouterProtocol push/present/pop/dismiss metódusokkal.

MegközelítésSzerkezetMikor használjuk
Globális NavigatorSingleton átmeneti metódusokkalKis projektek, prototípusok
Moduláris RouterRouter minden modulon belülVIPER, Clean Architecture
Protokoll RouterProtocol + implementáció Coordinator számáraMVVM-C, Coordinator minta

A minta története — A Router webframeworks-ekben jelent meg (URL Router — Rails Routes, Express.js) és adaptálták mobilfejlesztésre. iOS-ben a Router a VIPER növekedésével (2015-2017) vált népszerűvé. Androidban a Router — a Jetpack Navigation (2018) része, a Google szabványos navigációs megoldása. Ma a Router minden moduláris mobilalkalmazás-architektúra elválaszthatatlan része.

Router iOS-ben: implementáció Swift-ben

iOS Router — protokoll metódusokkal különböző navigációs típusokhoz. Az alap implementáció burkolja az UINavigationController-t. A Router kezelhet modális prezentációkat (present/dismiss), push/pop-ot a navigációs veremben, showDetail-t Split View Controller-hez és teljes képernyős prezentációkat (iOS 13+). A Router nem hoz létre ViewController-t — kap egy kész példányt és megjeleníti azt. A ViewController létrehozását gyár (Assembly, DI-konténer) vagy Coordinator végzi.

swift
// RouterProtocol iOS-hez
protocol RouterProtocol {
    func push(_ viewController: UIViewController, animated: Bool)
    func pop(animated: Bool)
    func popToRoot(animated: Bool)
    func present(_ viewController: UIViewController, animated: Bool)
    func dismiss(animated: Bool)
    func setViewControllers(_: [UIViewController], animated: Bool)
}

// Router implementáció UINavigationController-en keresztül
class NavigationRouter: RouterProtocol {
    private let navigationController: UINavigationController

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }

    func push(_ vc: UIViewController, animated: Bool) {
        if navigationController.presentedViewController {
            navigationController.dismiss(animated: false)
        }
        navigationController.pushViewController(vc, animated: animated)
    }

    func pop(animated: Bool) {
        navigationController.popViewController(animated: animated)
    }

    func popToRoot(animated: Bool) {
        navigationController.popToRootViewController(animated: animated)
    }

    func present(_ vc: UIViewController, animated: Bool) {
        navigationController.present(vc, animated: animated)
    }

    func dismiss(animated: Bool) {
        navigationController.dismiss(animated: animated)
    }

    func setViewControllers(_ vcs: [UIViewController], animated: Bool) {
        navigationController.setViewControllers(vcs, animated: animated)
    }
}

// Assembly — modul létrehozása Router-rel
protocol ProfileModuleFactory {
    func makeProfileView() -> UIViewController
}

Router VIPER-ben — minden VIPER modulnak saját Router-e van, amely tudja, mely képernyőket kell megnyitni az aktuális modulból. A Router létrehozza a következő modul ViewController-jét a gyáron keresztül és átadja a vezérlést. Router VIPER-ben — az egyetlen komponens, amely import UIKit-et tartalmaz (a View-n kívül). Ez leegyszerűsíti a Presenter és Interactor tesztelését: nem függenek az UIKit-től.

Router Androidban: Jetpack Navigation Component

Jetpack Navigation Component — szabványos router Androidhoz, a Google által ajánlva 2018 óta. A navigáció egy XML gráfban (nav_graph.xml) van definiálva: csomópontok (fragments, activities, destinations) és élek (actions). A NavController kezeli az átmeneteket: meghívja a FragmentManager.replace/add-t és kezeli a visszalépési vermet (back stack). A Navigation Component támogatja a deep link-eket, argumentumokat, átmeneti animációkat és a Safe Args-t a típusbiztos adatátvitelhez.

kotlin
// nav_graph.xml — navigációs gráf
<!-- @xml/nav_graph.xml -->
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_graph"
    app:startDestination="@id/loginFragment">

    <fragment android:id="@+id/loginFragment"
        android:name=".ui.login.LoginFragment">
        <action android:id="@+id/to_home"
            app:destination="@id/homeFragment" />
    </fragment>

    <fragment android:id="@+id/homeFragment"
        android:name=".ui.home.HomeFragment">
        <argument android:name="userId"
            android:defaultValue="0"
            app:argType="integer" />
        <deepLink app:uri="myapp://home/{userId}" />
    </fragment>
</navigation>

// Kotlin — navigáció NavController-en keresztül
class LoginFragment : Fragment() {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        binding.loginButton.setOnClickListener {
            val action = LoginFragmentDirections.toHome(userId = 42)
            findNavController().navigate(action)
        }
    }
}

// Safe Args — típusbiztos argumentumok
class HomeFragmentArgs : NavArgs {
    val userId: Int get() = arguments?.getInt("userId") ?: 0
}

// NavigationUI — integráció Toolbar, BottomNav, Drawer
class MainActivity : AppCompatActivity() {
    private lateinit var navController: NavController

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val navHost = supportFragmentManager
            .findFragmentById(R.id.nav_host_fragment) as NavHostFragment
        navController = navHost.navController
        NavigationUI.setupActionBarWithNavController(this, navController)
    }
}

Deep link-ek Android Navigation-ban — A Navigation Component támogatja az explicit deep link-eket (PendingIntent + NavDeepLinkBuilder) és implicit deep link-eket (intent-filter-en keresztül a manifesztumban). A deep link bármelyik nav_graph csomóponthoz vezethet. Push értesítések feldolgozása: a Notification létrehoz egy PendingIntent-et NavDeepLinkBuilder-rel, amely visszaállítja a back stack-et és megnyitja a kívánt képernyőt. A Navigation Component automatikusan kezeli a Up/Back gombokat és visszaviszi a felhasználót az előző képernyőre.

URL Routing: Deeplink és Universal Link útválasztás

URL Routing — útválasztás URL-sémák, deep link-ek és universal link-ek alapján. Az alkalmazás regisztrál egy sémát (myapp://profile/42) vagy egy universal link-et (https://example.com/profile/42). A Router elemzi az URL-t, kivonja a paramétereket (userId=42) és megnyitja a megfelelő képernyőt. Az URL Routing lehetővé teszi az alkalmazás külső megnyitását: weboldal linkjén, e-mailből, push értesítésből, QR kódból. Az iOS NSUserActivity + universal link-et használ, Android — intent-filter + deep link-et.

swift
// URL Router — deep link elemzés és navigáció
protocol URLRoute {
    var pattern: String { get }
    func navigate(parameters: [String: String], router: RouterProtocol)
}

struct ProfileRoute: URLRoute {
    let pattern = "myapp://profile/{userId}"

    func navigate(parameters: [String: String], router: RouterProtocol) {
        guard let userId = parameters["userId"] else { return }
        let profileVC = ProfileViewController(userId: userId)
        router.push(profileVC, animated: true)
    }
}

// URL Router — URL-ek hozzárendelése útvonalakhoz
class URLRouter {
    private var routes: [URLRoute] = []

    func handle(_ url: URL, router: RouterProtocol) {
        for route in routes {
            if let params = matchPattern(route.pattern, url: url) {
                route.navigate(parameters: params, router: router)
                return
            }
        }
    }
}

Deep link routing a gyakorlatban — az alkalmazásnak három állapotban kell feldolgoznia a deep link-et: nem indult (indítás deep link-kel), háttérben (visszaállítás háttérből), aktív (onNewIntent/SceneDelegate). Az URL Router-nek helyesen kell visszaállítania a back stack-et: profilképernyőre mutató deep link esetén a felhasználónak meg kell tudnia nyomni a Back gombot és visszatérni az előző képernyőre. Az iOS és Android eltérően kezeli a back stack-et — a Router-nek figyelembe kell vennie a platform jellemzőit.

A Router összehasonlítása Coordinator és Navigator

Router vs Coordinator — A Router arra a kérdésre válaszol, hogy "hogyan jelenítsük meg a képernyőt?" (push/present), a Coordinator — "melyik képernyőt jelenítsük meg?" (melyik flow-t indítsuk el). Router — navigációs eszköz, Coordinator — flow szervező. A Router-t a Coordinator használja. VIPER-ben a Router mindkét funkciót ellátja: eldönti, hová navigáljon és hogyan jelenítsen meg. MVVM-C-ben a Router — külön protokoll, amelyet a Coordinator használ. A minták nem zárják ki, hanem kiegészítik egymást.

JellemzőRouterCoordinatorNavigator
FókuszNavigációs mechanikaNavigációs flowGlobális hozzáférés
SzintUI-framework (push/present)Üzleti logika (flow)Infrastruktúra
Képernyő létrehozásaKész VC-t kapVC-t gyáron keresztül hozza létreVC-t hoz létre
ÉletciklusEgy navigációnkéntchildCoordinatorsSingleton

Router vs Navigator — Navigator — a Router elavult neve az iOS közösségben. Korai implementációkban a Navigator egy Singleton osztály volt átmeneti metódusokkal. Navigator — egy globális Router-singleton. A Navigator egyszerűbb, de rejtett függőségeket hoz létre. Protokollokon alapuló Router — tesztelhetőbb és modulárisabb. Navigator szigorú architektúra nélküli projektekhez alkalmas, Router — Clean Architecture és VIPER számára.

Gyakran ismételt kérdések

Mi a különbség a Router és a Coordinator között?

Router — absztrakció az UINavigationController felett (push/present/pop). Coordinator — réteg a Router felett, amely a flow-t kezeli (melyik képernyő jelenjen meg következőként). A Router a mechanikáért felel, a Coordinator — a navigációs logikáért. A Coordinator a Router-t használja az átmenetek végrehajtásához. VIPER-ben a Router mindkét funkciót egyesíti, MVVM-C-ben — szét vannak választva.

Kötelező a Router használata mobilalkalmazásban?

Nem. 3-5 képernyős alkalmazásoknál a navigationController.pushViewController közvetlen hívása normális megoldás. A Router 10+ képernyő, deep link-ek, push értesítések és moduláris architektúra esetén válik hasznossá. A Router leegyszerűsíti a navigáció tesztelését és lehetővé teszi az átmenetek központosított feldolgozását bármilyen forrásból (gomb, deep link, push).

Hogyan kapcsolódik a Router a Deep Links-hez?

URL Router — a Router kiterjesztése, amely elemzi a deep link-eket és universal link-eket. Az URL Router meghatározza az URL és az alkalmazás képernyője közötti megfelelést. Például, route myapp://profile/42 → ProfileViewController(userId: 42). Az URL Router központosítja a deep link-ek feldolgozását különböző forrásokból: push értesítések, QR kódok, email linkek, univerzális linkek.

Használható a Router Coordinator nélkül?

Igen. A Router működhet önállóan — globális Navigatorként vagy VIPER modul komponenseként. Router Coordinator nélkül — csupán az UINavigationController beágyazása egy protokoll mögé. Coordinator Router nélkül — nehezebb (a ViewController maga hívja a push/present-et), de lehetséges. Legjobb gyakorlat — Router + Coordinator együtt.

Az Androidban lévő Router ugyanaz, mint az iOS Router?

Funkcionálisan — igen, mindkettő központosítja a navigációt. Az implementáció eltérő: iOS Router — protokoll + osztály az UINavigationController körül; Android — Jetpack Navigation Component XML gráffal és NavController-rel. Az Android Router be van építve a framework-be (Navigation Component), iOS Router — külső implementáció. Az Android Router támogatja a Safe Args-t, az iOS Router nem — generics vagy Codable szükséges.

Összegzés

  • Router — útválasztási minta, amely beágyazza a képernyőátmenetek logikáját
  • iOS Router — protokoll push/present/pop metódusokkal az UINavigationController körül
  • Android Router — Jetpack Navigation Component XML nav_graph és NavController segítségével
  • URL Routing — útválasztás deep link-eken és univerzális linkeken keresztül
  • Router vs Coordinator — Router a mechanikáért, Coordinator a navigációs flow-ért felel
  • Alkalmazás — moduláris architektúra, deep link-ek, navigáció tesztelése

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is