Deferred Navigation — ano ito, mga prinsipyo at implementasyon

May-akda: IT Sectr Nai-publish: 2026-06-10 Oras ng pagbabasa: 9 min

Ang Deferred Navigation ay isang pattern ng naantalang nabigasyon kung saan ang paglipat sa susunod na screen ay nagaganap pagkatapos makumpleto ang isang asynchronous na operasyon, hindi direkta sa sandali ng aksyon ng gumagamit. Ayon sa Android Developers (2024), pinapayagan ng deferred navigation na maiwasan ang race condition sa pagitan ng nabigasyon at pag-load ng data, pati na rin pinapasimple ang paghawak ng mga transition mula sa mga push notification at Deeplink. Ang pangunahing pagkakaiba — ang ruta ay kinakalkula pagkatapos maging available ang lahat ng kinakailangang data.

Mga pangunahing punto

  • Deferred Navigation — naantalang nabigasyon, kung saan ang transition ay isinasagawa pagkatapos makumpleto ang mga asynchronous na operasyon
  • Direktang nabigasyon pinoproseso ang transition kaagad, deferred — naghihintay ng data
  • Karaniwang mga senaryo: awtorisasyon, Deeplink, mga push notification, pag-load ng configuration
  • Sa Android ay ipinapatupad sa pamamagitan ng Navigation Component na may mga callback at StateFlow
  • Sa iOS ginagamit ang Combine o async/await na may coordinator ng nabigasyon

Ano ang Deferred Navigation

Deferred Navigation ay isang architectural pattern kung saan ang desisyon sa nabigasyon ay ipinagpapaliban hanggang sa maging available ang lahat ng kinakailangang data. Hindi tulad ng direktang transition, kung saan pinindot ng gumagamit ang isang button at agad na napupunta sa isang bagong screen, pinaghihiwalay ng deferred navigation ang trigger event at ang aktwal na transition, nagdaragdag ng asynchronous na operasyon sa pagitan ng mga ito.

Sa arkitektura, ang Deferred Navigation ay batay sa pagbabago ng estado: ang pagpindot ng button ay nagpapasimula ng asynchronous na proseso, at ang subscription sa resulta nito ay nagpapatakbo ng nabigasyon. Ito ay lalong mahalaga sa mga application na may arkitekturang MVVM o MVI, kung saan ang ViewModel ay namamahala ng estado, at ang View (Activity, Fragment, SwiftUI View) ay nag-subscribe sa mga pagbabago at tumutugon sa pamamagitan ng transition. Ang ganitong approach ay nag-aalis ng direktang dependency sa pagitan ng UI at ng nabigasyong lohika.

Ayon sa Google I/O 2023, ang deferred navigation ay inirerekomenda para sa lahat ng senaryo kung saan ang nabigasyon ay nakadepende sa resulta ng network request, pagsusuri ng awtorisasyon, pag-load ng configuration o mga pahintulot. Ang pattern ay sapilitan din sa pagproseso ng Deeplink, kapag ang application ay kailangan munang magsimula, i-load ang root screen at pagkatapos lamang pumunta sa target na ruta.

Kailan kailangan ang naantalang nabigasyon

Deferred Navigation ay inilalapat sa mga senaryo kung saan ang direktang transition ay humahantong sa hindi tamang estado ng screen o mga error sa pag-load. Isaalang-alang natin ang apat na pangunahing kaso kung kailan sapilitan ang deferred navigation.

Awtorisasyon at pagpapatunay

Kung ang gumagamit ay nag-click sa protektadong nilalaman, dapat munang suriin ng application ang access token. Direktang nabigasyon sa screen ng nilalaman ay hahantong sa isang blangkong screen o error 401 kung ang token ay nag-expire. Sinusuri ng Deferred navigation ang token, at kung matagumpay lamang — pumupunta sa target na screen. Kung nabigo — nagre-redirect sa screen ng pag-login.

Pagproseso ng Deeplink

Kapag ang application ay binuksan sa pamamagitan ng isang panlabas na link, kailangan munang i-load ang root screen, ibalik ang estado ng nabigasyon at pagkatapos lamang isagawa ang transition sa pamamagitan ng Deeplink. Ang direktang nabigasyon sa target na screen nang walang root context ay hahantong sa mga anomalya: walang laman na navigation stack o sirang back stack.

Mga push notification na may nilalaman

Sa pag-tap sa isang push notification, ang application ay maaaring nasa tatlong estado: sarado, nasa background o aktibo. Tinutukoy ng Deferred Navigation ang estado ng application, nilo-load ang kinakailangang nilalaman at pagkatapos lamang ipinapakita ang target na screen. Pinapayagan ng iOS na iproseso ang senaryong ito sa pamamagitan ng UNNotificationContentExtension.

Dynamic na feature flag

Kung ang functionality ng screen ay pinamamahalaan ng isang feature flag mula sa server, pinapayagan ng deferred navigation na munang humiling ng configuration at pagkatapos lamang ipakita ang screen. Kung ang feature ay naka-disable, ang gumagamit ay nakakakita ng alternatibong nilalaman o placeholder sa halip na isang blangkong screen.

SenaryoDirektang nabigasyonDeferred Navigation
AwtorisasyonBlangkong screen sa nag-expire na tokenPag-redirect sa login
DeeplinkSirang back stackTamang navigation stack
PushPag-load nang walang kontekstoData handa bago ang transition
Feature flagPagpapakita ng hindi available na functionPlaceholder o alternatibo

Deferred Navigation vs direktang nabigasyon

Direktang nabigasyon (direct navigation) — tradisyonal na approach kung saan ang transition ay isinasagawa kaagad bilang tugon sa isang event. Pinindot ng gumagamit ang isang button, at agad na inilipat ng UI router ang screen. Ang approach na ito ay simple at predictable, ngunit limitado sa mga senaryo kung saan kailangan ang data mula sa server o pagsusuri ng mga kondisyon.

Deferred Navigation ay nagdaragdag ng isang layer sa anyo ng asynchronous na estado. Ang event ng gumagamit ay nagpapasimula ng isang operasyon, at ang subscription sa resulta ay namamahala ng nabigasyon. Pinapataas nito ang pagiging kumplikado ng code, ngunit nagbibigay ng flexibility: ang parehong trigger ay maaaring humantong sa iba't ibang mga screen depende sa na-load na data.

Ang pagpili sa pagitan ng dalawang approach ay depende sa mga kinakailangan: kung para sa pagpapakita ng screen ay hindi kinakailangan ang asynchronous na data — gamitin ang direktang nabigasyon. Kung ang screen ay depende sa resulta ng isang request, awtorisasyon o panlabas na kondisyon — sapilitan ang deferred navigation. Ang hybrid approach, kung saan ang bahagi ng mga transition ay direkta at ang bahagi ay naantala, ay ang pinakakaraniwang kasanayan sa mga pang-industriyang application.

Implementasyon sa Android: Navigation Component at ViewModel

Android Jetpack ay nagbibigay ng mga mekanismo para sa pagpapatupad ng Deferred Navigation sa antas ng arkitektura. Ang pangunahing ideya — ang ViewModel ay namamahala ng estado, at ang Activity o Fragment ay nag-subscribe sa mga pagbabago at nagpapatakbo ng nabigasyon sa pamamagitan ng NavController.

Deferred Navigation na may StateFlow

StateFlow sa Kotlin coroutines — perpektong tool para sa deferred navigation. Ina-update ng ViewModel ang StateFlow gamit ang navigation event, at ito ay inoobserbahan ng Activity at isinasagawa ang transition. Kapag na-proseso na ang event, ang StateFlow ay nililinis, pinipigilan ang paulit-ulit na nabigasyon.

kotlin
class MainViewModel : ViewModel() {
    private val _navigation = MutableSharedFlow<NavigationEvent>()
    val navigation: SharedFlow<NavigationEvent> = _navigation

    fun onDeepLinkReceived(link: String) {
        viewModelScope.launch {
            val data = resolveDeepLink(link)
            _navigation.emit(NavigationEvent.GoToScreen(data))
        }
    }
}

Deferred Navigation na may NavController

Sa Activity, ang subscription sa nabigasyon ay nagpapatakbo ng NavController na may ruta mula sa ViewModel. Para maiwasan ang paulit-ulit na nabigasyon sa pag-ikot ng screen, ginagamit ang NavigationEventWrapper na nagpoproseso ng event nang isang beses lamang. Ang Jetpack Navigation 2.7+ ay sumusuporta sa Safe Args para sa type-safe na pagpapadala ng argumento.

kotlin
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val vm: MainViewModel by viewModels()
        repeatOnLifecycle(Lifecycle.State.STARTED) {
            vm.navigation.collect { event ->
                when (event) {
                    is NavigationEvent.GoToScreen ->
                        findNavController(R.id.nav_host)
                            .navigate(event.route)
                }
            }
        }
    }
}

Implementasyon sa iOS: Coordinator Pattern at Combine

iOS ay walang built-in na Navigation Component na katulad ng Android Jetpack, kaya ang mga developer ay nagpapatupad ng Deferred Navigation sa pamamagitan ng Coordinator Pattern kasama ng Combine o async/await. Ang Coordinator ay namamahala ng stack ng mga screen at gumagawa ng mga desisyon sa nabigasyon batay sa na-load na data.

Coordinator na may Combine

Coordinator — isang bagay na namamahala ng nabigasyon sa pagitan ng mga ViewController. Kasama ng Combine, ang ViewModel ay naglalathala ng mga event sa pamamagitan ng PassthroughSubject, at ang Coordinator ay nag-subscribe sa mga ito at isinasagawa ang transition. Ang approach na ito ay ganap na naghihiwalay ng UI mula sa nabigasyong lohika at sumusunod sa mga rekomendasyon ng Apple para sa arkitektura ng application.

swift
final class AppCoordinator {
    private var cancellables = Set<AnyCancellable>()

    func start(viewModel: MainViewModel) {
        viewModel.$navigationDestination
            .compactMap { $0 }
            .sink { [weak self] destination in
                self?.navigateTo(destination)
            }
            .store(in: &cancellables)
    }
}

Deferred Navigation na may async/await

Swift 5.5 ay nagpakilala ng structured concurrency, na nagpapahintulot sa pagpapatupad ng naantalang nabigasyon sa pamamagitan ng async/await nang walang Combine. Ang ViewModel ay nagbibigay ng isang async function na nagbabalik ng ruta pagkatapos mag-load ng data. Tinatawag ng Coordinator ang function na ito sa Task at isinasagawa ang transition ayon sa natanggap na ruta.

swift
class AuthViewModel: ObservableObject {
    func resolveDeeplink(_ url: URL) async -> AppRoute? {
        guard let token = await AuthService.shared.getValidToken() else { return .login }
        return await DeeplinkRouter.resolve(url, token: token)
    }
}

// Sa Coordinator:
Task {
    if let route = await viewModel.resolveDeeplink(url) {
        navigateTo(route)
    }
}

Mga karaniwang pagkakamali at best practices

Deferred Navigation ay nagpapasimple ng pagproseso ng mga asynchronous na senaryo, ngunit nangangailangan ng disiplinadong approach sa pamamahala ng estado. Isaalang-alang natin ang mga pangunahing pagkakamali na ginagawa ng mga developer sa pagpapatupad ng deferred navigation.

Pagkakamali: nabigasyon bago matapos ang initialization

Ang pinakakaraniwang pagkakamali — pagsubok na gawin ang deferred navigation bago ang root screen ay ganap na na-initialize at ang NavController o Coordinator ay handa na para sa transition. Sa Android ito ay humahantong sa IllegalStateException, sa iOS — sa hindi natukoy na estado ng UI. Solusyon — tiyakin na ang lifecycle ng component ay nasa estado na STARTED o RESUMED bago simulan ang nabigasyon.

Pagkakamali: paulit-ulit na nabigasyon sa pagbalik sa screen

Kung ang StateFlow o Subject ay hindi nililinis ang event pagkatapos ng pagproseso, sa pagbalik sa nakaraang screen ang gumagamit ay maaaring awtomatikong ma-redirect sa parehong screen muli. Gumamit ng SharedFlow na may replay=0 sa Android o CurrentValueSubject na may nil pagkatapos ng pagproseso sa iOS, upang ang navigation event ay ma-trigger nang isang beses lamang.

Best Practice: isang NavController o Coordinator

Gumamit ng isang sentral na component para sa buong nabigasyon sa application. Kapag ang bawat Activity, Fragment o ViewController ay may sariling navigation controller, ang deferred navigation sa pagitan ng iba't ibang bahagi ng application ay nagiging magulo. Ang isang Coordinator ay nagpapadali sa debugging at pagsubok ng mga navigation scenario.

Best Practice: pagsubok ng mga naantalang navigation scenario

Ang Deferred Navigation ay mas mahirap subukan kaysa sa direktang nabigasyon dahil ang mga asynchronous na operasyon ay nagpapakilala ng factor ng oras. Gumamit ng TestDispatcher sa Android (kotlinx-coroutines-test) at XCTestExpectation sa iOS para sa simulation ng pag-load ng data at suriin na ang nabigasyon ay isinasagawa ayon sa inaasahang ruta. I-mock ang mga serbisyo ng awtorisasyon at deeplink para sa isolated na pagsubok ng bawat senaryo.

Mga madalas itanong

Ano ang pagkakaiba ng Deferred Navigation sa Deep Link?

Deferred Navigation ay isang pattern ng naantalang transition na maaaring ilapat sa anumang asynchronous na senaryo. Ang Deep Link ay isa sa mga trigger para sa deferred navigation, ngunit hindi lamang ito. Ang awtorisasyon at feature flag ay gumagamit din ng naantalang nabigasyon.

Maaari bang pagsamahin ang deferred at direct navigation?

Oo, karamihan sa mga application ay gumagamit ng hybrid approach. Ang screen ng listahan ng produkto (walang asynchronous dependencies) ay maaaring gumamit ng direktang nabigasyon, at ang screen ng detalye na may pag-load ng data — deferred. Ang paghahati ay tinutukoy ng arkitektura ng partikular na screen.

Paano maiiwasan ang race condition sa deferred navigation?

Gumamit ng SharedFlow na walang replay sa Android at combineLatest na walang buffering sa iOS. Kanselahin ang mga nakaraang subscription sa bagong trigger. Ito ay ginagarantiyahan na ang huling navigation event lamang ang pinoproseso.

Sinusuportahan ba ng Jetpack Compose ang deferred navigation?

Oo, sa Compose ang deferred navigation ay ipinapatupad sa pamamagitan ng subscription sa StateFlow ng ViewModel at pagtawag ng NavController.navigate sa LaunchedEffect. Inirerekomenda ng Google ang paggamit ng Navigation Compose na may event model para sa mga deferred scenario.

Paano hawakan ang deferred navigation kapag ang application ay pinaliit?

Ipagpaliban ang nabigasyon hanggang sa maging aktibo muli ang application. Sa Android gamitin ang Lifecycle.State.STARTED para sa pag-filter ng mga event. Sa iOS suriin ang UIApplication.State sa Combine o async/await block.

Buod

  • Deferred Navigation — pattern kung saan ang transition ay isinasagawa pagkatapos makumpleto ang isang asynchronous na operasyon
  • Pangunahing senaryo: awtorisasyon, Deeplink, push notification, feature flag
  • StateFlow/SharedFlow sa Android at Combine/async-await sa iOS — mga tool sa implementasyon
  • Deferred Navigation hindi tulad ng direkta ay hindi nagdudulot ng race condition sa asynchronous na pag-load
  • Navigation Component sa Android at Coordinator Pattern sa iOS — mga pangunahing arkitektura
  • Isang NavController/Coordinator ay sapilitan para sa consistent na nabigasyon
  • Pagsubok ng deferred navigation ay nangangailangan ng TestDispatcher at mga mock para sa mga asynchronous na serbisyo

Gagawa kami ng mobile application na turnkey

Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.

Pag-usapan ang proyekto

Basahin din