riverpod_navigator 0.11.0 copy "riverpod_navigator: ^0.11.0" to clipboard
riverpod_navigator: ^0.11.0 copied to clipboard

outdated

Simple but powerfull Flutter navigation with riverpod, freezed and Navigator 2.0.

Navigator for Riverpod #

Simple but powerfull navigation library (based on Flutter Navigator 2.0, Riverpod, and Freezed) that solves the following problems: #

  • Strictly typed navigation:
    You can use navigate([Home(), Books(), Book(id: bookId)]); instead of navigate('home/books/$bookId'); in your code.
  • Easier coding:
    The problem of navigation is reduced to manipulation an immutable collection.
  • Better separation of concerns: UI x Model (thanks to riverpod 👍):
    Navigation logic can be developed and tested without typing a single flutter widget.
  • Asynchronous navigation:
    Before starting navigation, prepare all necessary asynchronous operations, e.g.
    • loading data for new screen
    • save data from the previous screen
  • Dependence on external providers:
    The navigation state may also depend on external providers, e.g. on login status
  • Possibility to configure many navigation parameters

The mission #

Take a look at the following terms related to url path home/books/book;id=2

  • string-path: final stringPath = 'home/books/book;id=2';
  • string-segment - the string-path consists of three string-segments: 'home', 'books' and 'book;id=2'
  • typed-segment - the typed-segment is immutable class that defines string-segment: HomeSegment(), BooksSegment() and BookSegment(id:2)
  • typed-path: typed-path can be understood as List
  • navigation-stack of Flutter Navigator 2.0 is a stack of screens, parameterized by typed-segment: HomeScreen(HomeSegment())) => BooksScreen(BooksSegment()) => BookScreen(BookSegment(id:3))

The mission of navigation is to keep string-path <= typed-path => navigation-stack always in sync. With the typed-path as the source of the truth.

How does it work #

If anyone wants to understand how the riverpod_navigator package works, let them look at riverpod_navigator_example. It validates the idea of collaboration Riverpod + Freezed + Flutter Navigator 2.0.

Simple example #

The full code is available here here.

Step1 - imutable classes for typed-segment #

We use freezed-package for generation immutable clasess (that defines typed-segments).

It's a good idea to be familiar with the freezed-package (including support for JSON serialization).

From the following SimpleSegment class declaration, the freezed package generates two classes: HomeSegment and PageSegment.

@freezed
class SimpleSegment with _$SimpleSegment, TypedSegment {
  SimpleSegment._();
  factory SimpleSegment.home() = HomeSegment;
  factory SimpleSegment.page({required String title}) = PageSegment;

  factory SimpleSegment.fromJson(Map<String, dynamic> json) => _$SimpleSegmentFromJson(json);
}

Step2 - navigator parameterization #

Extends the RiverpodNavigator class as follows:

class AppNavigator extends RiverpodNavigator {
  AppNavigator(Ref ref)
      : super(
          ref,
          // which screen to run when the application starts
          initPath: [HomeSegment()],
          // JSON serialization of "typed-segment" 
          fromJson: SimpleSegment.fromJson,
          // build a screen from segment
          screenBuilder: (segment) => (segment as SimpleSegment).map(
            home: HomeScreen.new,
            page: PageScreen.new,
          ),
        );
}

Step3 - use the navigator in MaterialApp.router #

If you are familiar with the Flutter Navigator 2.0 and the riverpod, the following code is understandable:

class App extends ConsumerWidget {
  const App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // for all widgets with riverpod support, the navigator is available via riverpodNavigatorProvider
    final navigator = ref.read(riverpodNavigatorProvider);
    return MaterialApp.router(
      title: 'Riverpod Navigator Example',
      routerDelegate: navigator.routerDelegate,
      routeInformationParser: navigator.routeInformationParser,
      debugShowCheckedModeBanner: false,
    );
  }
}

Step4 - runApp #

void main() => runApp(
      ProviderScope(
        overrides: [
          riverpodNavigatorCreatorProvider.overrideWithValue(AppNavigator.new),
        ],
        child: const App(),
      ),
    );

Step5 - widgets for screens #

Creating screen widgets is probably an understandable part of the example.

Only the navigation to the new screen is interesting:

//  getting navigation stack "HomeScreen(HomeSegment()) => PageScreen(PageSegment(title: 'Page title'))".
ref.read(riverpodNavigatorProvider).navigate([HomeSegment(), PageSegment(title: 'Page')]);

or

// getting navigation stack "HomeScreen(HomeSegment())".
ref.read(riverpodNavigatorProvider).navigate([HomeSegment()]);

Code simplification #

  • using the functional_widget package simplifies widgets typing.
  • some code repeats - it is moved to common dart file

A modified version of the previous example is here: here.

Other feartures #

Async navigation and splash screen #

todo

An alternative way to configure the navigator: using the router concept #

todo

More TypedSegment roots #

todo

When the navigation status depends on other providers #

todo

Testing #

Navigation logic can be developed and tested without typing a single flutter widget.

todo

Roadmap #

I prepared this package for my new project. Its further development depends on whether it will be used by the community.

  • finish examples
  • proofreading because my English is not good. Community help is warmly welcomed.
  • testing on mobile (tested so far for windows desktop and web)
    Navigator.onPopPage may need improvements.
  • nested navigation flow
    I think everything is ready, nested ProviderScope can solve nested navigation too.
  • BlockGUI widget (block the GUI while asynchronous navigation is waiting to complete)
  • parameterization alowing cupertino
25
likes
0
pub points
57%
popularity

Publisher

unverified uploader

Simple but powerfull Flutter navigation with riverpod, freezed and Navigator 2.0.

Repository (GitHub)
View/report issues

License

unknown (LICENSE)

Dependencies

flutter, freezed_annotation, hooks_riverpod, json_annotation, meta, riverpod, tuple

More

Packages that depend on riverpod_navigator