Deferred Navigation — bu nədir, prinsipləri və tətbiqi

Müəllif: IT Sectr Dərc olunub: 2026-06-10 Oxuma vaxtı: 9 dəq

Deferred Navigation — gecikmiş naviqasiya nümunəsidir, burada növbəti ekrana keçid asinxron əməliyyat tamamlandıqdan sonra baş verir, istifadəçinin hərəkəti anında deyil. Android Developers (2024)-ə görə, deferred navigation naviqasiya və məlumat yükləmə arasında yarış vəziyyətindən qaçmağa imkan verir, həmçinin push bildirişləri və Deeplink-dən keçidlərin işlənməsini sadələşdirir. Əsas fərq — marşrut bütün lazımi məlumatlar əldə edildikdən sonra hesablanır.

Əsas məqamlar

  • Deferred Navigation — gecikmiş naviqasiya, burada keçid asinxron əməliyyatlar tamamlandıqdan sonra icra olunur
  • Birbaşa naviqasiya keçidi dərhal idarə edir, deferred — məlumatları gözləyir
  • Tipik ssenarilər: avtorizasiya, Deeplink, push bildirişləri, konfiqurasiya yükləmə
  • Android-də Navigation Component və callbacks və StateFlow vasitəsilə həyata keçirilir
  • iOS-da Combine və ya async/await naviqasiya koordinatoru ilə istifadə olunur

Deferred Navigation nədir

Deferred Navigation — memarlıq nümunəsidir, burada naviqasiya qərarı bütün lazımi məlumatlar əldə olunana qədər təxirə salınır. Birbaşa keçiddən fərqli olaraq, istifadəçi düyməni basır və dərhal yeni ekrana düşür, deferred navigation trigger-hadisəni və faktiki keçidi ayırır, aralarında asinxron əməliyyat əlavə edir.

Memarlıq baxımından Deferred Navigation vəziyyət dəyişikliyinə əsaslanır: düymənin basılması asinxron prosesi başladır, nəticəyə abunəlik isə naviqasiyanı işə salır. Bu, xüsusilə MVVM və ya MVI arxitekturası olan proqramlarda vacibdir, burada ViewModel vəziyyəti idarə edir, View (Activity, Fragment, SwiftUI View) isə dəyişikliklərə abunə olur və keçidlə reaksiya verir. Bu yanaşma UI ilə naviqasiya məntiqi arasında birbaşa asılılığı aradan qaldırır.

Google I/O 2023 məlumatlarına görə, deferred navigation şəbəkə sorğusunun nəticəsindən, avtorizasiya yoxlanışından, konfiqurasiya yükləməsindən və ya icazələrdən asılı olan bütün ssenarilər üçün tövsiyə olunur. Bu nümunə həmçinin Deeplink-in işlənməsi zamanı məcburidir, proqram əvvəlcə işə düşməli, kök ekranı yükləməli və yalnız bundan sonra hədəf marşruta keçməlidir.

Gecikmiş naviqasiya nə vaxt lazımdır

Deferred Navigation birbaşa keçidin ekranın səhv vəziyyətinə və ya yükləmə xətalarına səbəb olduğu ssenarilərdə tətbiq olunur. Gecikmiş naviqasiyanın məcburi olduğu dörd əsas halı nəzərdən keçirək.

Avtorizasiya və autentifikasiya

İstifadəçi qorunan məzmuna klik edərsə, proqram əvvəlcə giriş tokenini yoxlamalıdır. Birbaşa naviqasiya məzmun ekranına tokenin müddəti bitibsə boş ekrana və ya 401 xətasına səbəb olacaq. Deferred navigation tokeni yoxlayır və yalnız uğur olduqda — hədəf ekrana keçir. Uğursuzluq halında — giriş ekranına yönləndirir.

Deeplink-in işlənməsi

Proqram xarici keçid vasitəsilə açıldıqda, əvvəlcə kök ekranı yükləmək, naviqasiya vəziyyətini bərpa etmək və yalnız sonra Deeplink üzrə keçidi yerinə yetirmək lazımdır. Kök konteksti olmadan hədəf ekrana birbaşa naviqasiya anomaliyalara səbəb olacaq: boş naviqasiya yığını və ya sınmış back stack.

Məzmunlu push bildirişləri

Push bildirişinə toxunduqda proqram üç vəziyyətdə ola bilər: bağlı, fon və ya aktiv. Deferred Navigation proqramın vəziyyətini müəyyən edir, lazımi məzmunu yükləyir və yalnız sonra hədəf ekranı göstərir. iOS bu ssenarini UNNotificationContentExtension vasitəsilə idarə etməyə imkan verir.

Dinamik feature flag

Ekranın funksionallığı serverdən feature flag ilə idarə olunursa, deferred navigation əvvəlcə konfiqurasiyanı sorğulamağa və yalnız sonra ekranı göstərməyə imkan verir. Funksiya söndürülübsə — istifadəçi boş ekran əvəzinə alternativ məzmun və ya placeholder görür.

SsenariBirbaşa naviqasiyaDeferred Navigation
AvtorizasiyaToken müddəti bitdikdə boş ekranGiriş səhifəsinə yönləndirmə
DeeplinkBack stack sınmasıDüzgün naviqasiya yığını
PushKontekstsiz yükləməMəlumat keçiddən əvvəl hazırdır
Feature flagƏlçatmaz funksiyanın göstərilməsiPlaceholder və ya alternativ

Deferred Navigation vs birbaşa naviqasiya

Birbaşa naviqasiya (direct navigation) — ənənəvi yanaşma, burada keçid hadisəyə cavab olaraq dərhal icra olunur. İstifadəçi düyməni basır və UI router dərhal ekranı dəyişir. Bu yanaşma sadə və proqnozlaşdırıla biləndir, lakin server məlumatları və ya şərtlərin yoxlanılması tələb olunan ssenarilərdə məhduddur.

Deferred Navigation asinxron vəziyyət şəklində bir təbəqə əlavə edir. İstifadəçinin hadisəsi əməliyyatı başladır, nəticəyə abunəlik isə naviqasiyanı idarə edir. Bu kodun mürəkkəbliyini artırır, lakin çeviklik verir: eyni trigger yüklənmiş məlumatlardan asılı olaraq müxtəlif ekranlara apara bilər.

İki yanaşma arasında seçim tələblərdən asılıdır: ekranın göstərilməsi üçün asinxron məlumat tələb olunmursa — birbaşa naviqasiyadan istifadə edin. Ekran sorğunun nəticəsindən, avtorizasiyadan və ya xarici şərtlərdən asılıdırsa — deferred navigation məcburidir. Hibrid yanaşma, keçidlərin bir hissəsinin birbaşa, bir hissəsinin isə gecikmiş olduğu — istehsalat proqramlarında ən geniş yayılmış təcrübədir.

Android-də tətbiqi: Navigation Component və ViewModel

Android Jetpack Deferred Navigation-ın memarlıq səviyyəsində tətbiqi üçün mexanizmlər təqdim edir. Əsas ideya — ViewModel vəziyyəti idarə edir, Activity və ya Fragment isə dəyişikliklərə abunə olur və NavController vasitəsilə naviqasiyanı işə salır.

StateFlow ilə Deferred Navigation

StateFlow Kotlin coroutines-də deferred navigation üçün ideal alətdir. ViewModel naviqasiya hadisəsi ilə StateFlow-u yeniləyir, Activity isə onu müşahidə edir və keçidi yerinə yetirir. Hadisə işləndikdə StateFlow təmizlənir, təkrar naviqasiyanın qarşısını alır.

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

NavController ilə Deferred Navigation

Activity-də naviqasiyaya abunəlik ViewModel-dən marşrutla NavController-ı işə salır. Ekran fırlanması zamanı təkrar naviqasiyanın qarşısını almaq üçün NavigationEventWrapper istifadə olunur, hadisəni yalnız bir dəfə işləyir. Jetpack Navigation 2.7+ arqumentlərin tip-təhlükəsiz ötürülməsi üçün Safe Args-ı dəstəkləyir.

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

iOS-da tətbiqi: Coordinator Pattern və Combine

iOS-da Android Jetpack-ə bənzər daxili Navigation Component yoxdur, buna görə tərtibatçılar Deferred Navigation-ı Coordinator Pattern vasitəsilə Combine və ya async/await ilə birlikdə həyata keçirirlər. Coordinator ekran yığınını idarə edir və yüklənmiş məlumatlar əsasında naviqasiya qərarları qəbul edir.

Combine ilə Coordinator

Coordinator — ViewController-lar arasında naviqasiyanı idarə edən obyekt. Combine ilə birlikdə ViewModel hadisələri PassthroughSubject vasitəsilə yayımlayır, Coordinator isə onlara abunə olur və keçidi yerinə yetirir. Bu yanaşma UI-nı naviqasiya məntiqindən tamamilə ayırır və Apple-ın proqram arxitekturası üzrə tövsiyələrinə uyğundur.

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

async/await ilə Deferred Navigation

Swift 5.5 structured concurrency təqdim etdi ki, bu da Combine olmadan async/await vasitəsilə gecikmiş naviqasiyanı həyata keçirməyə imkan verir. ViewModel məlumat yükləndikdən sonra marşrutu qaytaran async-funksiya təqdim edir. Coordinator bu funksiyanı Task-da çağırır və alınan marşrut üzrə keçidi yerinə yetirir.

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

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

Tipik səhvlər və best practices

Deferred Navigation asinxron ssenarilərin işlənməsini sadələşdirir, lakin vəziyyətin idarə edilməsinə intizamlı yanaşma tələb edir. Deferred navigation tətbiq edərkən tərtibatçıların buraxdığı əsas səhvləri nəzərdən keçirək.

Səhv: inisializasiya tamamlanmamış naviqasiya

Ən çox yayılmış səhv — kök ekran tam inisializasiya olunmamış və NavController və ya Coordinator keçidə hazır olmamış deferred navigation etməyə cəhd etməkdir. Android-də bu IllegalStateException-a, iOS-da — qeyri-müəyyən UI vəziyyətinə səbəb olur. Həll yolu — naviqasiyanı işə salmazdan əvvəl komponentin həyat dövrünün STARTED və ya RESUMED vəziyyətində olduğundan əmin olun.

Səhv: ekrana qayıtdıqda təkrar naviqasiya

Əgər StateFlow və ya Subject hadisəni işləndikdən sonra təmizləmirsə, əvvəlki ekrana qayıtdıqda istifadəçi avtomatik olaraq eyni ekrana yenidən yönləndirilə bilər. Android-də replay=0 olan SharedFlow və ya iOS-da işlənmədən sonra nil olan CurrentValueSubject istifadə edin ki, naviqasiya hadisəsi yalnız bir dəfə işləsin.

Best Practice: vahid NavController və ya Coordinator

Proqramda bütün naviqasiya üçün bir mərkəzi komponentdən istifadə edin. Hər Activity, Fragment və ya ViewController-in öz naviqasiya kontrolleri olduqda, proqramın müxtəlif hissələri arasında deferred navigation xaotik olur. Vahid Coordinator naviqasiya ssenarilərinin debug və testini asanlaşdırır.

Best Practice: gecikmiş naviqasiya ssenarilərinin test edilməsi

Deferred Navigation birbaşa naviqasiyadan daha çətin test olunur, çünki asinxron əməliyyatlar zaman faktoru gətirir. Android-də TestDispatcher (kotlinx-coroutines-test) və iOS-da XCTestExpectation istifadə edərək məlumat yükləməsini simulyasiya edin və naviqasiyanın gözlənilən marşrut üzrə icra olunduğunu yoxlayın. Hər ssenarinin izolyasiya olunmuş testi üçün avtorizasiya və deeplink xidmətlərini mock edin.

Tez-tez verilən suallar

Deferred Navigation Deep Link-dən nə ilə fərqlənir?

Deferred Navigation — gecikmiş keçid nümunəsidir, istənilən asinxron ssenaridə tətbiq oluna bilər. Deep Link deferred navigation üçün triggerlərdən biridir, lakin yeganə deyil. Avtorizasiya və feature flaglar da gecikmiş naviqasiyadan istifadə edir.

Deferred və direct navigation birləşdirilə bilərmi?

Bəli, əksər proqramlar hibrid yanaşmadan istifadə edir. Məhsul siyahısı ekranı (asinxron asılılıqlar olmadan) birbaşa naviqasiyadan istifadə edə bilər, məlumat yükləməsi olan detal ekranı isə deferred. Bölgü konkret ekranın arxitekturası ilə müəyyən edilir.

Deferred navigation zamanı race condition-dən necə qaçmaq olar?

İstifadə edin Android-də replay olmadan SharedFlow və iOS-da bufferləşdirməsiz combineLatest. Yeni trigger olduqda əvvəlki abunəlikləri ləğv edin. Bu, yalnız son naviqasiya hadisəsinin işlənməsini təmin edir.

Jetpack Compose deferred navigation-ı dəstəkləyirmi?

Bəli, Compose-da deferred navigation ViewModel-in StateFlow-na abunəlik və LaunchedEffect-də NavController.navigate çağırışı ilə həyata keçirilir. Google deferred ssenarilər üçün Navigation Compose-dan hadisə modeli ilə istifadə etməyi tövsiyə edir.

Kiçildilmiş proqramda deferred navigation necə idarə olunmalıdır?

Təxirə salın naviqasiyanı proqram yenidən aktiv olana qədər. Android-də hadisələri filtrləmək üçün Lifecycle.State.STARTED istifadə edin. iOS-da Combine və ya async/await blokunda UIApplication.State-i yoxlayın.

Nəticə

  • Deferred Navigation — keçidin asinxron əməliyyat tamamlandıqdan sonra icra olunduğu nümunə
  • Əsas ssenarilər: avtorizasiya, Deeplink, push bildirişləri, feature flaglar
  • StateFlow/SharedFlow Android-də və Combine/async-await iOS-da — tətbiq alətləri
  • Deferred Navigation birbaşadan fərqli olaraq asinxron yükləmədə yarış vəziyyətinə səbəb olmur
  • Navigation Component Android-də və Coordinator Pattern iOS-da — əsas arxitekturalar
  • Vahid NavController/Coordinator ardıcıl naviqasiya üçün məcburidir
  • Test etmə deferred navigation asinxron xidmətlər üçün TestDispatcher və mocklar tələb edir

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun