Migrate from Getx to Riverpod/GoRouter/Others in Flutter (Part 2)
Background
Read the Part 1 for migrating state management functions from Getx to Riverpod.
This part will cover the route cases and other small cases.
Below route cases are based on this baseline implicitly:
go_router: ^12.1.3Router
Global Routes
Before
routes = [ GetPage( name: '/home', page: () => const HomeView(), ), ... ];
GetMaterialApp( getPages: routes, initialRoute: '/home', defaultTransition: Transition.rightToLeft, navigatorKey: _navigatorKey, navigatorObservers: <NavigatorObserver>[ AnalyticsService.observer, ], ... );After
Using riverpod provider for router because I have the case to navigate the page from the Controller layer.
GoRouter supports two methods for navigation api. One is to use the context (BuildContext), like context.go('/home'), context is available in UI Widget.
Another one is to use the same apis on GoRouter class without context.
routes = [ GoRoute( path: '/home', builder: (_, __) => const HomeView(), ), ... ];
@Riverpod(keepAlive: true) GoRouter appRouter(AppRouterRef ref) { return GoRouter( initialLocation: '/home', routes: routes, debugLogDiagnostics: true, navigatorKey: _navigatorKey, observers: <NavigatorObserver>[ AnalyticsService.observer, ], ); }
// to use riverpod provider, the App widget should extend from `ConsumerWidget` MaterialApp.router( routerConfig: ref.watch(appRouterProvider), ... );Navigation
ref.watch(appRouterProvider) is good to use in controller if context is not available, like ref.watch(appRouterProvider).pop().
Get.back()tocontext.pop()Get.back(result: 'done')tocontext.pop('done')Get.toNamed('/home')tocontext.push('/home')Get.to(const HomeView()): seems GoRouter doesn’t support such navigation, have to register it to routes first then usepush.Get.offAllNamed('/home')'tocontext.go('/home')
Arguments in navigation
Pass the arg to next page:
Get.toNamed('/home', arguments: 'abc')tocontext.push('/home', extra: 'abc')
Get the arg in route for next page:
GoRoute( path: '/home', builder: (_, state) => HomeView(state.extra as String), ),Get.arguments in Getx can be accessed in widgets and controllers without context. To access the extra arg in controller (or provider) in riverpod, the arg should be passed:
@riverpodclass HomeController extends _$HomeController { HomeState build(String args) { // args is 'abc' ... } ...}
class HomeView extends ConsumerWidget { const HomeView(this.args, {super.key});
@override Widget build(BuildContext context, ref) { final homeState = ref.watch(homeControllerProvider(args)); final homeController = ref.watch(homeControllerProvider(args).notifier); ... }}Nested Routes
I didn’t get the way to use GoRouter for nested routes 😅. so migrate it from Getx to the flutter built-in Navigator. The official doc is a good example.
Only call out: Don’t use GoRouter api to navigate the Navigator’s route.
Other cases
Get.width and Get.height can be replaced by
final FlutterView _view = WidgetsBinding.instance.platformDispatcher.views.first;
double get width => _view.physicalSize.width / _view.devicePixelRatio;
double get height => _view.physicalSize.height / _view.devicePixelRatio;For Get.context, this can be replaced by the real context if the widget is migrated to riverpod on part1.
An alternative to get the context outside widgets, make it globally:
final navigatorKey = GlobalKey<NavigatorState>();
BuildContext get currentContext => navigatorKey.currentContext!;Updates
Created on 2023-12-10
