blob: 389afe4063b5992186884f1382c435aa9739206a [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
/// This sample app demonstrates how to provide a codec for complex extra data.
void main() => runApp(const MyApp());
/// The router configuration.
final GoRouter _router = GoRouter(
routes: <RouteBase>[
GoRoute(
path: '/',
builder: (BuildContext context, GoRouterState state) =>
const HomeScreen(),
),
],
extraCodec: const MyExtraCodec(),
);
/// The main app.
class MyApp extends StatelessWidget {
/// Constructs a [MyApp]
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routerConfig: _router,
);
}
}
/// The home screen.
class HomeScreen extends StatelessWidget {
/// Constructs a [HomeScreen].
const HomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Home Screen')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
"If running in web, use the browser's backward and forward button to test extra codec after setting extra several times."),
Text(
'The extra for this page is: ${GoRouterState.of(context).extra}'),
ElevatedButton(
onPressed: () => context.go('/', extra: ComplexData1('data')),
child: const Text('Set extra to ComplexData1'),
),
ElevatedButton(
onPressed: () => context.go('/', extra: ComplexData2('data')),
child: const Text('Set extra to ComplexData2'),
),
],
),
),
);
}
}
/// A complex class.
class ComplexData1 {
/// Create a complex object.
ComplexData1(this.data);
/// The data.
final String data;
@override
String toString() => 'ComplexData1(data: $data)';
}
/// A complex class.
class ComplexData2 {
/// Create a complex object.
ComplexData2(this.data);
/// The data.
final String data;
@override
String toString() => 'ComplexData2(data: $data)';
}
/// A codec that can serialize both [ComplexData1] and [ComplexData2].
class MyExtraCodec extends Codec<Object?, Object?> {
/// Create a codec.
const MyExtraCodec();
@override
Converter<Object?, Object?> get decoder => const _MyExtraDecoder();
@override
Converter<Object?, Object?> get encoder => const _MyExtraEncoder();
}
class _MyExtraDecoder extends Converter<Object?, Object?> {
const _MyExtraDecoder();
@override
Object? convert(Object? input) {
if (input == null) {
return null;
}
final List<Object?> inputAsList = input as List<Object?>;
if (inputAsList[0] == 'ComplexData1') {
return ComplexData1(inputAsList[1]! as String);
}
if (inputAsList[0] == 'ComplexData2') {
return ComplexData2(inputAsList[1]! as String);
}
throw FormatException('Unable to parse input: $input');
}
}
class _MyExtraEncoder extends Converter<Object?, Object?> {
const _MyExtraEncoder();
@override
Object? convert(Object? input) {
if (input == null) {
return null;
}
switch (input) {
case ComplexData1 _:
return <Object?>['ComplexData1', input.data];
case ComplexData2 _:
return <Object?>['ComplexData2', input.data];
default:
throw FormatException('Cannot encode type ${input.runtimeType}');
}
}
}