Skip to content

Commit 05be51a

Browse files
robelatorclaude
andcommitted
+Fix critical bugs and simplify docs
- Fix RouteManager missing dispose() causing memory leaks - Deprecate StatelessRouteManager (creates new controller on every rebuild) - Fix incorrect method names in README - Simplify example and documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent fe50dde commit 05be51a

18 files changed

Lines changed: 266 additions & 687 deletions

README.md

Lines changed: 36 additions & 211 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
[![banner](https://github.com/dev-cetera/df_router/blob/v0.5.4/doc/assets/banner.png?raw=true)](https://github.com/dev-cetera)
1+
[![banner](https://github.com/dev-cetera/df_router/blob/v0.5.5/doc/assets/banner.png?raw=true)](https://github.com/dev-cetera)
22

33
[![pub](https://img.shields.io/pub/v/df_router.svg)](https://pub.dev/packages/df_router)
4-
[![tag](https://img.shields.io/badge/Tag-v0.5.4-purple?logo=github)](https://github.com/dev-cetera/df_router/tree/v0.5.4)
4+
[![tag](https://img.shields.io/badge/Tag-v0.5.5-purple?logo=github)](https://github.com/dev-cetera/df_router/tree/v0.5.5)
55
[![buymeacoffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-FFDD00?logo=buy-me-a-coffee&logoColor=black)](https://www.buymeacoffee.com/dev_cetera)
66
[![sponsor](https://img.shields.io/badge/Sponsor-grey?logo=github-sponsors&logoColor=pink)](https://github.com/sponsors/dev-cetera)
7-
[![patreon](https://img.shields.io/badge/Patreon-grey?logo=patreon)](https://www.patreon.com/t0mb3rr)
7+
[![patreon](https://img.shields.io/badge/Patreon-grey?logo=patreon)](https://www.patreon.com/robelator)
88
[![discord](https://img.shields.io/badge/Discord-5865F2?logo=discord&logoColor=white)](https://discord.gg/gEQ8y2nfyX)
99
[![instagram](https://img.shields.io/badge/Instagram-E4405F?logo=instagram&logoColor=white)](https://www.instagram.com/dev_cetera/)
1010
[![license](https://img.shields.io/badge/License-MIT-blue.svg)](https://raw.githubusercontent.com/dev-cetera/df_router/main/LICENSE)
@@ -15,254 +15,79 @@
1515

1616
## Summary
1717

18-
A lightweight router designed for ease of use and efficient state management. Explore it in action with this live web app: https://dev-cetera.github.io/df_router/chat?chatId=123456.
18+
A lightweight Flutter router with state management. [Live demo](https://dev-cetera.github.io/df_router/chat?chatId=123456).
1919

20-
## Features
21-
22-
- **Declarative Routing:** Define your routes and their corresponding widgets in a clean, list-based manner.
23-
- **Stateful Routes:** `RouteState` objects represent unique routes, including paths, query parameters, and strongly-typed `extra` data.
24-
- **Widget Caching & Preservation:** Control whether route widgets are preserved in memory (`shouldPreserve`) or pre-built (`shouldPrebuild`) for performance.
25-
- **Customizable Transitions:** Easily define custom page transitions called "effects" or use the provided `MaterialEffect` and `CupertinoEffect`.
26-
- **Persistent UI Wrapper:** Add common UI elements like headers, footers, or navigation bars that persist across route changes.
27-
- **Easy Navigation:** Navigate using `RouteState` objects or simple path strings.
28-
- **Typed `extra` Data:** Pass strongly-typed data between routes.
29-
30-
## Usage
31-
32-
### 1. Define Your RouteStates
33-
34-
Create classes that extend `RouteState` for each distinct route in your application. These classes encapsulate the path and can manage query parameters.
20+
## Quick Start
3521

3622
```dart
37-
final class HomeRouteState extends RouteState {
38-
HomeRouteState()
39-
: super.parse(
40-
'/home',
41-
// Use QuickForwardtEffect() as the default transtion effect for this
42-
// route. This can be overridden when pushing this route.
43-
animationEffect: const QuickForwardEffect(),
44-
);
45-
}
23+
import 'package:df_router/df_router.dart';
24+
import 'package:flutter/material.dart';
4625
47-
// This route is only used in the RouteManager, so it does not need to
48-
// be pushed directly. It is a base route for the chat feature.
49-
final class BaseChatRouteState extends RouteState {
50-
BaseChatRouteState({Map<String, String>? queryParameters})
51-
: super.parse(
52-
'/chat',
53-
queryParameters: queryParameters,
54-
// Use a different animation effect for this route.
55-
animationEffect: const SlideDownEffect(),
56-
);
26+
void main() => runApp(const MyApp());
5727
58-
BaseChatRouteState.from(RouteState other) : super(other.uri);
28+
// 1. Define routes.
29+
final class HomeRoute extends RouteState {
30+
HomeRoute() : super.parse('/home');
5931
}
6032
61-
final class ChatRouteState extends BaseChatRouteState {
33+
final class ChatRoute extends RouteState {
6234
final String chatId;
63-
64-
ChatRouteState({required this.chatId}) : super(queryParameters: {'chatId': chatId});
65-
66-
ChatRouteState.from(super.other)
35+
ChatRoute({required this.chatId})
36+
: super.parse('/chat', queryParameters: {'chatId': chatId});
37+
ChatRoute.from(RouteState other)
6738
: chatId = other.uri.queryParameters['chatId'] ?? '',
68-
super.from();
39+
super(other.uri);
6940
}
70-
```
71-
72-
### 2. Configure RouteStateManager
7341
74-
In your MaterialApp (or CupertinoApp), use the RouteStateManager widget to define your application's routing configuration.
75-
76-
```dart
42+
// 2. Setup RouteManager.
7743
class MyApp extends StatelessWidget {
7844
const MyApp({super.key});
7945
8046
@override
8147
Widget build(BuildContext context) {
8248
return MaterialApp(
83-
//home: // Do not use "home", as it conflicts with RouteManager. Use
84-
// "builder" instead.
8549
builder: (context, child) {
8650
return RouteManager(
87-
fallbackRouteState: () => HomeRouteState(),
51+
fallbackRouteState: HomeRoute.new,
8852
builders: [
8953
RouteBuilder(
90-
routeState: HomeRouteState(),
91-
// Pre-build the HomeScreen even if the initial route is not
92-
// HomeRouteState. This is useful for performance optimization.
93-
shouldPrebuild: true,
94-
// Preserve the HomeScreen widget to avoid rebuilding it.
95-
shouldPreserve: true,
96-
builder: (context, routeState) => HomeScreen(routeState: HomeRouteState()),
54+
routeState: HomeRoute(),
55+
builder: (context, state) => const HomeScreen(),
9756
),
9857
RouteBuilder(
99-
// Use the BaseChatRouteState instead of the ChatRouteState
100-
// since it does not require a chatId to be pushed.
101-
routeState: BaseChatRouteState(),
102-
builder:
103-
(context, routeState) => ChatScreen(routeState: ChatRouteState.from(routeState)),
58+
routeState: ChatRoute(chatId: ''),
59+
builder: (context, state) => ChatScreen(route: ChatRoute.from(state)),
10460
),
10561
],
10662
);
10763
},
10864
);
10965
}
11066
}
111-
```
112-
113-
### 3. Create Your Screen Widgets
114-
115-
Your screen widgets should use the `RouteWidgetMixin` to easily access the current `RouteState`.
11667
117-
```dart
118-
class HomeScreen extends StatelessWidget with RouteWidgetMixin {
119-
@override
120-
final HomeRouteState? routeState;
121-
const HomeScreen({super.key, this.routeState});
122-
123-
@override
124-
Widget build(BuildContext context) {
125-
return Scaffold(
126-
appBar: AppBar(title: const Text('Home')),
127-
backgroundColor: Colors.green,
128-
body: Center(
129-
child: ElevatedButton(
130-
onPressed: () {
131-
final controller = RouteController.of(context);
132-
controller.push(
133-
ChatRouteState(chatId: '123456'),
134-
// Override the default animation effect for this push.
135-
animationEffect: const CupertinoEffect(),
136-
);
137-
},
138-
child: const Text('Go to Chat'),
139-
),
140-
),
141-
);
142-
}
143-
}
144-
145-
class ChatScreen extends StatelessWidget with RouteWidgetMixin {
146-
@override
147-
final ChatRouteState? routeState;
148-
149-
const ChatScreen({super.key, this.routeState});
150-
151-
@override
152-
Widget build(BuildContext context) {
153-
return Scaffold(
154-
appBar: AppBar(title: Text('Chat - ${routeState?.chatId}')),
155-
backgroundColor: Colors.blue,
156-
body: Center(
157-
child: Column(
158-
mainAxisAlignment: MainAxisAlignment.center,
159-
children: [
160-
ElevatedButton(
161-
onPressed: () {
162-
final controller = RouteController.of(context);
163-
controller.goBackward();
164-
},
165-
child: const Text('Go Back - Default Effect'),
166-
),
167-
ElevatedButton(
168-
onPressed: () {
169-
final controller = RouteController.of(context);
170-
controller.goBackward(animationEffect: const QuickBackEffect());
171-
},
172-
child: const Text('Go Back - Quick Back Effect'),
173-
),
174-
ElevatedButton(
175-
onPressed: () {
176-
final controller = RouteController.of(context);
177-
controller.push(HomeRouteState());
178-
},
179-
child: const Text('Go Home - Default Effect'),
180-
),
181-
ElevatedButton(
182-
onPressed: () {
183-
final controller = RouteController.of(context);
184-
controller.push(HomeRouteState().copyWith(animationEffect: const MaterialEffect()));
185-
},
186-
child: const Text('Go Home - Material Effect'),
187-
),
188-
ElevatedButton(
189-
onPressed: () {
190-
final controller = RouteController.of(context);
191-
controller.push(HomeRouteState(), animationEffect: const PageFlapDown());
192-
},
193-
child: const Text('Go Home - Page Flap Down Effect'),
194-
),
195-
],
196-
),
197-
),
198-
);
199-
}
200-
}
68+
// 3. Navigate.
69+
RouteController.of(context).push(ChatRoute(chatId: '123'));
70+
RouteController.of(context).goBackward();
20171
```
20272

203-
## 4. Navigation
204-
205-
Access the RouteStateController to navigate:
206-
207-
```dart
208-
final controller = RouteStateController.of(context);
209-
210-
// Push the home screen with a material effect.
211-
controller.push(HomeRouteState(), animationEffect: const CupertinoEffect());
212-
controller.push(HomeRouteState().copyWith(animationEffect: const MaterialEffect()));
213-
214-
// Go back.
215-
controller.pushBack();
216-
217-
// Remove a specific route to free up resources.
218-
controller.removeStatesFromCache([HomeRouteState()]);
219-
220-
// Clear the entire widget cache.
221-
controller.clearCache([HomeRouteState()]);
222-
223-
// Add a route to the cache without navigating. This will preload it.
224-
controller.addToCache([HomeRouteState()]);
225-
226-
// Reset the cache to its initial state. This honours the shouldPrebuild property.
227-
controller.resetState();
228-
229-
// Get the current state, e.g. HomeRouteState();
230-
final current = controller.current;
73+
## Features
23174

232-
// Get the requested state, which is what was typed in the URL bar, e.g. "/home?query=123" may return an instance of HomeRouteState(). This will return nul if the URL does not match any defined route.
233-
final requested = controller.requested;
234-
```
75+
- Declarative route definitions
76+
- Query parameter support
77+
- Typed route data via `extra`
78+
- Widget caching with `shouldPreserve` and `shouldPrebuild`
79+
- Custom transitions (`MaterialEffect`, `CupertinoEffect`, etc.)
23580

23681
<!-- END _README_CONTENT -->
23782

23883
---
23984

240-
🔍 For more information, refer to the [API reference](https://pub.dev/documentation/df_router/).
241-
242-
---
243-
244-
## 💬 Contributing and Discussions
245-
246-
This is an open-source project, and we warmly welcome contributions from everyone, regardless of experience level. Whether you're a seasoned developer or just starting out, contributing to this project is a fantastic way to learn, share your knowledge, and make a meaningful impact on the community.
247-
248-
### ☝️ Ways you can contribute
249-
250-
- **Find us on Discord:** Feel free to ask questions and engage with the community here: https://discord.gg/gEQ8y2nfyX.
251-
- **Share your ideas:** Every perspective matters, and your ideas can spark innovation.
252-
- **Help others:** Engage with other users by offering advice, solutions, or troubleshooting assistance.
253-
- **Report bugs:** Help us identify and fix issues to make the project more robust.
254-
- **Suggest improvements or new features:** Your ideas can help shape the future of the project.
255-
- **Help clarify documentation:** Good documentation is key to accessibility. You can make it easier for others to get started by improving or expanding our documentation.
256-
- **Write articles:** Share your knowledge by writing tutorials, guides, or blog posts about your experiences with the project. It's a great way to contribute and help others learn.
257-
258-
No matter how you choose to contribute, your involvement is greatly appreciated and valued!
259-
260-
### ☕ We drink a lot of coffee...
85+
For more details, see the [API reference](https://pub.dev/documentation/df_router/).
26186

262-
If you're enjoying this package and find it valuable, consider showing your appreciation with a small donation. Every bit helps in supporting future development. You can donate here: https://www.buymeacoffee.com/dev_cetera
87+
## Contributing
26388

264-
<a href="https://www.buymeacoffee.com/dev_cetera" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/default-orange.png" height="40"></a>
89+
Join our [Discord](https://discord.gg/gEQ8y2nfyX) or support us on [Buy Me A Coffee](https://www.buymeacoffee.com/dev_cetera).
26590

266-
## LICENSE
91+
## License
26792

268-
This project is released under the [MIT License](https://raw.githubusercontent.com/dev-cetera/df_router/main/LICENSE). See [LICENSE](https://raw.githubusercontent.com/dev-cetera/df_router/main/LICENSE) for more information.
93+
[MIT License](https://raw.githubusercontent.com/dev-cetera/df_router/main/LICENSE)

0 commit comments

Comments
 (0)