Router — bases du pattern de routage dans iOS et Android

Auteur : IT Sectr Publié le : 2026-02-19 Temps de lecture : 9 min

Router (routeur) — un pattern architectural qui centralise la logique de navigation entre les écrans de l'application. Le Router détermine où et comment naviguer lors d'un événement. Sous iOS, le Router abstrait UINavigationController et les segues ; sous Android — FragmentManager et NavController de Jetpack Navigation. Le Router peut fonctionner comme un pattern indépendant ou comme un composant de Coordinator (Router-per-Coordinator) et VIPER (Router-per-module). Plus de détails — dans le Android Navigation Component Guide.

Points clés

  • Router — pattern de routage qui centralise la navigation entre les écrans
  • Deux niveaux — le Router peut être un composant de Coordinator ou un pattern indépendant
  • iOS Router — abstraction sur UINavigationController avec les méthodes push/present/pop
  • Android Router — Jetpack Navigation Component avec NavController et deep links
  • URL Routing — routage basé sur les schémas d'URL (deeplink, universal link)

Qu'est-ce que Router : essence du pattern de routage

Router — un pattern qui encapsule la logique de transition entre les écrans. L'idée principale : le ViewController (ou Presenter/ViewModel) n'appelle pas directement navigationController.pushViewController, mais notifie le Router de son intention de naviguer. Le Router décide quel ViewController créer et comment l'afficher. Le Router peut être simple (un ensemble de méthodes de navigation) ou complexe (avec routage par schémas d'URL, deep links et notifications push).

Trois approches du Router — Router comme service (Navigator singleton global), Router comme composant de module (approche VIPER), Router comme protocole (abstraction pour Coordinator). Router global — simplicité (une instance par application) — populaire dans les petits projets. Router modulaire — chaque fonctionnalité a son propre Router — standard VIPER et Clean Architecture. Router par protocole — utilisé dans Coordinator : RouterProtocol avec les méthodes push/present/pop/dismiss.

ApprocheStructureQuand l'utiliser
Navigator globalSingleton avec méthodes de navigationPetits projets, prototypes
Router modulaireRouter dans chaque moduleVIPER, Clean Architecture
Router par protocoleProtocole + implémentation pour CoordinatorMVVM-C, Coordinator pattern

Histoire du pattern — le Router est apparu dans les frameworks web (URL Router — Rails Routes, Express.js) et a été adapté pour le développement mobile. Sous iOS, le Router est devenu populaire avec l'essor de VIPER (2015-2017). Sous Android, le Router fait partie de Jetpack Navigation (2018), la solution standard de Google pour la navigation. Aujourd'hui, le Router fait partie intégrante de toute architecture modulaire d'applications mobiles.

Router sous iOS : implémentation en Swift

iOS Router — un protocole avec des méthodes pour différents types de navigation. L'implémentation de base englobe UINavigationController. Le Router peut gérer les présentations modales (present/dismiss), les push/pop dans la pile de navigation, showDetail pour Split View Controller et les présentations plein écran (iOS 13+). Le Router ne crée pas de ViewControllers — il reçoit une instance prête et l'affiche. La création des ViewControllers est gérée par une fabrique (Assembly, conteneur DI) ou un Coordinator.

swift
// RouterProtocol pour iOS
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)
}

// Implémentation de Router via UINavigationController
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 — création d'un module avec Router
protocol ProfileModuleFactory {
    func makeProfileView() -> UIViewController
}

Router dans VIPER — chaque module VIPER a son propre Router, qui sait quels écrans ouvrir à partir du module actuel. Le Router crée le ViewController du module suivant via une fabrique et passe le contrôle. Le Router dans VIPER est le seul composant qui contient import UIKit (sauf View). Cela simplifie les tests du Presenter et de l'Interactor : ils ne dépendent pas d'UIKit.

Router sous Android : Jetpack Navigation Component

Jetpack Navigation Component — le routeur standard pour Android, recommandé par Google depuis 2018. La navigation est définie dans un graphe XML (nav_graph.xml) : nœuds (fragments, activities, destinations) et arêtes (actions). NavController gère les transitions : appelle FragmentManager.replace/add et gère la pile arrière. Navigation Component prend en charge les deep links, les arguments, les animations de transition et Safe Args pour le passage de données type-safe.

kotlin
// nav_graph.xml — graphe de navigation
<!-- @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 — navigation via NavController
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 — arguments type-safe
class HomeFragmentArgs : NavArgs {
    val userId: Int get() = arguments?.getInt("userId") ?: 0
}

// NavigationUI — intégration avec 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 links dans Android Navigation — Navigation Component prend en charge les deep links explicites (PendingIntent + NavDeepLinkBuilder) et implicites (via intent-filter dans le manifeste). Un deep link peut mener à n'importe quel nœud du nav_graph. Gestion des notifications push : la Notification crée un PendingIntent avec NavDeepLinkBuilder, qui restaure la pile arrière et ouvre l'écran souhaité. Navigation Component gère automatiquement les boutons Up/Back et ramène l'utilisateur à l'écran précédent.

URL Routing : routage Deeplink et Universal Link

URL Routing — routage basé sur les schémas d'URL, les deep links et les universal links. L'application enregistre un schéma (myapp://profile/42) ou un universal link (https://example.com/profile/42). Le Router analyse l'URL, extrait les paramètres (userId=42) et ouvre l'écran correspondant. L'URL Routing permet d'ouvrir l'application de l'extérieur : via un lien depuis un site web, un e-mail, une notification push, un code QR. iOS utilise NSUserActivity + universal link, Android — intent-filter + deep link.

swift
// URL Router — analyse de deep link et navigation
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 — mappage des URLs avec les routes
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
            }
        }
    }
}

Routage deep link en pratique — l'application doit gérer les deep links dans trois états : non lancée (lancement avec deep link), en arrière-plan (restauration depuis l'arrière-plan), active (onNewIntent/SceneDelegate). Le URL Router doit restaurer correctement la pile arrière : lors d'un deep link vers un écran de profil, l'utilisateur doit pouvoir appuyer sur Retour et revenir à l'écran précédent. iOS et Android gèrent les piles arrière différemment — le Router doit tenir compte des spécificités de la plateforme.

Comparaison du Router avec Coordinator et Navigator

Router vs Coordinator — le Router répond à la question « comment afficher un écran ? » (push/present), le Coordinator — « quel écran afficher ? » (quel flux lancer). Le Router est un outil de navigation, le Coordinator est un organisateur de flux. Le Coordinator utilise le Router. Dans VIPER, le Router remplit les deux fonctions : décider où aller et comment l'afficher. Dans MVVM-C, le Router est un protocole séparé utilisé par le Coordinator. Les patterns ne s'excluent pas mais se complètent.

CaractéristiqueRouterCoordinatorNavigator
FocusMécanique de navigationFlux de navigationAccès global
NiveauFramework UI (push/present)Logique métier (flux)Infrastructure
Création d'écransReçoit VC prêtCrée VC via fabriqueCrée VC
Cycle de vieUn par navigationchildCoordinatorsSingleton

Router vs Navigator — Navigator est un nom plus ancien pour Router dans la communauté iOS. Dans les premières implémentations, Navigator était une classe Singleton avec des méthodes de navigation. Navigator est un Router singleton global. Navigator est plus simple mais crée des dépendances cachées. Le Router basé sur les protocoles est plus testable et modulaire. Navigator convient aux projets sans architecture stricte, Router — pour Clean Architecture et VIPER.

Questions fréquentes

Quelle est la différence entre Router et Coordinator ?

Router est une abstraction sur UINavigationController (push/present/pop). Coordinator est une couche au-dessus du Router qui gère le flux (quel écran afficher ensuite). Le Router s'occupe de la mécanique, le Coordinator de la logique de navigation. Le Coordinator utilise le Router pour effectuer les transitions. Dans VIPER, le Router combine les deux fonctions ; dans MVVM-C, elles sont séparées.

Est-il obligatoire d'utiliser Router dans une application mobile ?

Non. Pour les applications avec 3 à 5 écrans, les appels directs à navigationController.pushViewController sont une solution parfaitement acceptable. Le Router devient utile avec 10+ écrans, des deep links, des notifications push et une architecture modulaire. Le Router simplifie les tests de navigation et permet un traitement centralisé des transitions depuis n'importe quelle source (bouton, deep link, notification push).

Comment Router est-il lié aux Deep Links ?

URL Router est une extension du Router qui analyse les deep links et les universal links. URL Router détermine la correspondance entre les URLs et les écrans de l'application. Par exemple, route myapp://profile/42 → ProfileViewController(userId: 42). URL Router centralise le traitement des deep links provenant de différentes sources : notifications push, codes QR, liens e-mail, liens universels.

Peut-on utiliser Router sans Coordinator ?

Oui. Le Router peut fonctionner indépendamment — comme un Navigator global ou comme un composant de module VIPER. Router sans Coordinator consiste simplement à encapsuler UINavigationController derrière un protocole. Coordinator sans Router est plus complexe (le ViewController appelle push/present directement), mais possible. La meilleure pratique est Router + Coordinator ensemble.

Le Router sous Android est-il le même que le Router iOS ?

Fonctionnellement — oui, tous deux centralisent la navigation. L'implémentation est différente : iOS Router — protocole + classe autour de UINavigationController ; Android — Jetpack Navigation Component avec graphe XML et NavController. Android Router est intégré au framework (Navigation Component), iOS Router est une implémentation tierce. Android Router prend en charge Safe Args, iOS Router non (nécessite des generics ou Codable).

Résumé

  • Router — pattern de routage qui encapsule la logique de transition entre les écrans
  • iOS Router — protocole avec méthodes push/present/pop autour de UINavigationController
  • Android Router — Jetpack Navigation Component avec XML nav_graph et NavController
  • URL Routing — routage via deep links et universal links
  • Router vs Coordinator — Router gère la mécanique, Coordinator gère le flux de navigation
  • Application — architecture modulaire, deep links, tests de navigation

Nous développerons une application mobile clé en main

IT Sectr crée des applications iOS et Android pour les startups et les entreprises depuis 2017. Nous vous conseillerons et vous proposerons la meilleure solution.

Discuter du projet

Lisez aussi