'Flutter deepLinking navigate from initial screen(home screen) to next screen(college screen) after refreshing data passed become null
dependencies using [get: ^4.3.4,uni_links: ^0.5.1]
main.dart build method :
@override
Widget build(BuildContext context) {
return MaterialApp.router(
debugShowCheckedModeBanner: false,
title: 'Navigator 2.0 Deep Link',
theme: ThemeData(
primarySwatch: Colors.blue,
),
routerDelegate: routerDelegate,
routeInformationParser: const MyRouteInformationParser(),
);
}
I have using routerDelegate and routeInformationParser for navigation...
Home screen onPress code :
onPressed: () {
return routerDelegate.pushPage(
name: '/college',
arguments: {
"screenCode" : 7,
}
);
},
below code how I have receiving param data from navigated file :
class College extends StatefulWidget {
final Map<String,dynamic> arguments;
const College({Key? key,required this.arguments}) : super(key: key);
@override
_CollegeState createState() => _CollegeState();
}
information_parser.dart file :
import 'package:flutter/material.dart';
class MyRouteInformationParser
extends RouteInformationParser<List<RouteSettings>> {
const MyRouteInformationParser() : super();
@override
Future<List<RouteSettings>> parseRouteInformation(
RouteInformation routeInformation) {
final uri = Uri.parse(routeInformation.location!);
if (uri.pathSegments.isEmpty) {
return Future.value([const RouteSettings(name: '/')]);
}
final routeSettings = uri.pathSegments
.map((pathSegment) => RouteSettings(
name: '/$pathSegment',
arguments: pathSegment == uri.pathSegments.last
? uri.queryParameters
: null,
))
.toList();
return Future.value(routeSettings);
}
@override
RouteInformation restoreRouteInformation(List<RouteSettings> configuration) {
final location = configuration.last.name;
final arguments = _restoreArguments(configuration.last);
return RouteInformation(location: '$location$arguments');
}
String _restoreArguments(RouteSettings routeSettings) {
if(routeSettings.name == '/college') {
return '?id=${(routeSettings.arguments as Map)['screenCode'].toString()}';
} else {
return '';
}
}
}
delegate.dart file :
import 'package:flutter/material.dart';
import 'package:nav_bar/ui/college.dart';
import 'package:nav_bar/ui/hostel.dart';
import 'package:nav_bar/ui/stadium.dart';
import '../router/transition_delegate.dart';
import '../ui/home.dart';
class MyRouterDelegate extends RouterDelegate<List<RouteSettings>>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<List<RouteSettings>> {
final _pages = <Page>[];
@override
final navigatorKey = GlobalKey<NavigatorState>();
@override
List<Page> get currentConfiguration => List.of(_pages);
@override
Widget build(BuildContext context) {
return Navigator(
key: navigatorKey,
pages: List.of(_pages),
onPopPage: _onPopPage,
transitionDelegate: const MyTransitionDelegate());
}
@override
Future<bool> popRoute() {
if (_pages.length > 1) {
_pages.removeLast();
notifyListeners();
return Future.value(true);
}
return _confirmAppExit();
}
@override
Future<void> setNewRoutePath(List<RouteSettings> configuration) {
_setPath(configuration
.map((routeSettings) => _createPage(routeSettings))
.toList());
return Future.value(null);
}
void parseRoute(Uri uri) {
if (uri.pathSegments.isEmpty) {
setNewRoutePath([const RouteSettings(name: '/')]);
} else {
setNewRoutePath(uri.pathSegments
.map((pathSegment) => RouteSettings(
name: '/$pathSegment',
arguments: pathSegment == uri.pathSegments.last
? uri.queryParameters
: null,
))
.toList());
}
}
bool _onPopPage(Route route, dynamic result) {
if (!route.didPop(result)) return false;
popRoute();
return true;
}
void _setPath(List<Page> pages) {
_pages.clear();
_pages.addAll(pages);
if (_pages.first.name != '/') {
_pages.insert(0, _createPage(const RouteSettings(name: '/')));
}
notifyListeners();
}
void pushPage({required String name, dynamic arguments}) {
_pages.add(_createPage(RouteSettings(name: name, arguments: arguments)));
notifyListeners();
}
MaterialPage _createPage(RouteSettings routeSettings) {
Widget child;
switch (routeSettings.name) {
case '/':
child = const HomePage();
break;
case '/college':
child = College(arguments: routeSettings.arguments as Map<String,dynamic>);
break;
case '/hostel':
child = Hostel();
break;
case '/stadium':
child = Stadium();
break;
default:
child = Scaffold(
appBar: AppBar(title: const Text('404')),
body: const Center(child: Text('Page not found')),
);
}
return MaterialPage(
child: child,
key: Key(routeSettings.toString()) as LocalKey,
name: routeSettings.name,
arguments: routeSettings.arguments,
);
}
Future<bool> _confirmAppExit() async {
final result = await showDialog<bool>(
context: navigatorKey!.currentContext!,
builder: (context) {
return AlertDialog(
title: const Text('Exit App'),
content: const Text('Are you sure you want to exit the app?'),
actions: [
TextButton(
child: const Text('Cancel'),
onPressed: () => Navigator.pop(context, true),
),
TextButton(
child: const Text('Confirm'),
onPressed: () => Navigator.pop(context, false),
),
],
);
});
return result ?? true;
}
}
After navigation my url will be http://localhost:56127/#/college?id=7
my issue is after refresh that screen param data have changed to null like below
http://localhost:56127/#/college?id=null
Please revert how to resolve?
Solution 1:[1]
Issue fixed :
I have done small mistake
onPressed: () {
return routerDelegate.pushPage(
name: '/college',
arguments: {
"screenCode" : 7,
}
);
},
if(routeSettings.name == '/college') {
return '?id=${(routeSettings.arguments as Map)['screenCode'].toString()}';
}
in onPressed function I declare key name as screenCode. but in routeSettings query Param I have declared as id.....so changed id to screenCode... fixed
Solution 2:[2]
Use Hive or secure storage to save your params locally. It won't get lost after refresh. Just read the saved params when you need it.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Harihara dhamodaran |
Solution 2 | Minjin Gelegdorj |