riverpod_navigator 0.16.0 copy "riverpod_navigator: ^0.16.0" to clipboard
riverpod_navigator: ^0.16.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.

Note: There is a one-to-one relationship between the given segment and the screen (HomeSegment - HomeScreen, BookSegment - BookScreen). In the following text, I sometimes confuse the two terms..

Installation #

After clonning repository, go to examples\doc subdirectory and execute:

  • flutter create .
  • flutter pub get
  • flutter pub run build_runner build --delete-conflicting-outputs

Simple example #

Step1 - imutable classes for typed-segment #

We use freezed-package for generation immutable clasess (that defines typed-segment's).

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

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

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

  factory SegmentGrp.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
          [HomeSegment()],
          [
            // JSON serialization of HomeSegment and PageSegment
            RRoutes<SegmentGrp>(SegmentGrp.fromJson, [
              // build a screen from segment
              RRoute<HomeSegment>(HomeScreen.new),
              RRoute<PageSegment>(PageScreen.new),
            ])
          ],
        );
}

Step3 - use the RiverpodNavigator in MaterialApp.router #

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

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

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:

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

or

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

Code of the example

The full code is available here: simple.dart.

See Other features for other doc and samples #

See What's under the hood for riverpod_navigation principle #

Comparison with go_router #

This chapter is inspired by this riverpod issue: Examples of go_router using riverpod.

example go_router code lines riverpod_navigator code lines
main source code 70 source code 84
redirection source code 167 source code 149

If you are interested in preparing another go_router example, I will try to do it.

Roadmap #

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

  • proofreading because my English is not good. Community help is warmly welcomed.
  • testing on mobile (tested so far for windows desktop and web)
  • 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