برنامه نویسی

Go Router Navigation Observer – Community Dev

GO_ROUTER یکی از محبوب ترین بسته ها برای مدیریت ناوبری در یک برنامه Flutter است و از آنجا که بخشی از تیم Flutter شد ، به راه حل اصلی توصیه شده تبدیل شده است.

استفاده از آن بسیار آسان و در عین حال غنی از ویژگی است.

با این حال ، با معرفی ShellRouteمشاهده جریان ناوبری در برنامه شما و داشتن مسیرهایی که از تغییرات ناوبری “آگاه هستند” دشوارتر شده است. همانطور که در این شماره برجسته شد ، وقتی اضافه می کنید ShellRoute، برنامه واکنش پذیری را نسبت به تغییرات مسیر از دست می دهد: NavigationObserver دیگر تحریک نشده است.

در حالی که منتظر یک راه حل رسمی یا راه حل داخلی از تیم Flutter هستیم ، ما هنوز هم می توانیم با گوش دادن به آن رفتار آگاهانه مسیر را پیاده سازی کنیم GoRouterDelegateبشر

کد زیر به GoRouterDelegate در طول چرخه عمر ویجت و از وضعیت داخلی به همراه مقایسه مسیر بالا برای افشای تماس های تماس در پاسخ به رویدادهای ناوبری استفاده می کند. البته ، این می تواند متناسب با نیازهای شما باشد – برای مثال ، واکنش به تغییرات پارامتر پرس و جو و موارد دیگر.

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

/// A mixin that allows a widget to be aware of the current route.
mixin GoRouterAware<T extends StatefulWidget> on State<T> {
  /// The route to be aware of.
  late final Uri _observerLocation;

  /// The current state of the [_observerLocation].
  late _GoRouterAwareState _state;

  /// go router delegate.
  late GoRouterDelegate _delegate;

  /// The context of the widget.
  late BuildContext _context;

  /// The location of the top route
  Uri? _currentLocation;

  @override
  void initState() {
    _context = context;

    final router = GoRouter.of(_context);

    _state = _GoRouterAwareState.topRoute;
    _observerLocation = router.state.uri;
    _delegate = router.routerDelegate;

    _onChange();
    _delegate.addListener(_onChange);
    super.initState();
  }

  @override
  void didChangeDependencies() {
    _context = context;
    super.didChangeDependencies();
  }

  void _onChange() {
    _currentLocation = GoRouter.of(_context).state.uri;

    if (_currentLocation == null) {
      return;
    }

    /// If the current route is the top route and the current location is the same as the observer location then [_observerLocation] is the top route.
    if (_state.isTopRoute &&
        _sameLocation(_currentLocation!, _observerLocation)) {
      didPush();
      return;
    }

    /// If the current route is pushed next and the current location is the same as the observer location then [_observerLocation] is returned to the top route.
    if (_state.isPushedNext &&
        _sameLocation(_currentLocation!, _observerLocation)) {
      didPopNext();
      _state = _GoRouterAwareState.topRoute;
      return;
    }

    /// If the current route is not the top route and the current location contains the observer location then [_observerLocation] is no longer the top route.
    if (!_sameLocation(_currentLocation!, _observerLocation) &&
        _currentLocation!.path.toString().contains(_observerLocation.path)) {
      _state = _GoRouterAwareState.pushedNext;
      didPushNext();
      return;
    }

    /// If the current route is the top route and the current location does not contain the observer location then [_observerLocation] is popped off.
    if (_state.isTopRoute &&
        !_currentLocation!.path.toString().contains(_observerLocation.path)) {
      didPop();
      _state = _GoRouterAwareState.poppedOff;
      return;
    }
  }

  /// Check if two locations have the same path.
  bool _sameLocation(Uri a, Uri b) {
    return a.path.toString() == b.path.toString();
  }

  /// Called when the top route has been popped off, and the current route
  /// shows up.
  void didPopNext() {}

  /// Called when the current route has been pushed.
  void didPush() {}

  /// Called when the current route has been popped off.
  void didPop() {}

  /// Called when a new route has been pushed, and the current route is no
  /// longer visible.
  void didPushNext() {}

  @override
  void dispose() {
    _delegate.removeListener(_onChange);
    super.dispose();
  }
}

enum _GoRouterAwareState {
  pushedNext,
  topRoute,
  poppedOff;

  bool get isTopRoute => this == topRoute;
  bool get isPushedNext => this == pushedNext;
  bool get isPoppedOff => this == poppedOff;
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

پیوند GitHub.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا