Flutter插件hopper的特性与使用指南
Flutter插件hopper的特性与使用指南
A package for using Flutter Navigator 2.0.
特性
- 支持深度链接。
- 支持将参数传递给与路径相关的其他页面。
- 支持异步调用,如
await hopNamed('/setting_page')
。 - 支持守卫。
为什么我编写了这个插件?
我为一个客户开发了一个使用 Flutter Navigator 1.0 的应用程序。我需要一个新的插件来支持深度链接,而 Navigator 1.0 不支持这一点。因此,我决定尝试一些在 pub.dev 上的现有包,比如 beamer
这个包很好用,但不幸的是它不支持 await beamNamed(...etc)
。我在 GitHub 上发起了一个讨论(截至2022年2月6日),作者提到这将在未来添加。
所以我决定创建这个包,并将其迁移到我的应用中。我也希望尽快完成这个任务(移动应用开发)。
这个包直到1.0.0版本只用了2天就完成了编写。
入门指南
简单的应用程序,只有一个首页
- 将插件添加到你的
pubspec.yaml
文件中:
dependencies:
flutter:
sdk: flutter
hopper: ^1.2.0
- 创建你的
main.dart
文件并添加以下代码:
import 'package:counter/router/classes.dart';
import 'package:flutter/material.dart';
import 'package:hopper/hopper.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final routerDelegate = AppRouter();
final routeInformationParser = AppRouteInformationParser();
MyApp({Key? key}) : super(key: key);
// 这个小部件是你的应用的根。
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Flutter Demo',
routerDelegate: routerDelegate,
routeInformationParser: routeInformationParser,
);
}
}
- 在
lib
文件夹内创建一个名为router
的文件夹,并在其中创建一个名为classes.dart
的文件(你可以选择任何名称,但需要导入它),然后添加以下代码:
import 'package:counter/home_page.dart';
import 'package:flutter/material.dart';
import 'package:hopper/hopper.dart';
class AppRouter extends AbstractAppRouter {
final GlobalKey<NavigatorState> navigatorKey;
static const String initialRoute = '/';
AppRouter()
: navigatorKey = GlobalKey<NavigatorState>(),
super((AbstractAppRouter appRouter) => AppNavigationManager(appRouter));
}
class AppNavigationManager extends AbstractAppNavigationManager {
final AbstractAppRouter routerDelegate;
AppNavigationManager(this.routerDelegate) : super(routerDelegate);
@override
List<AppLocation> get locations => [
HomeLocation(),
];
}
class HomeLocation extends AppLocation {
static const String route = '/';
@override
List<Pattern> get pathPatterns => [route];
@override
List<AppPage> buildPages(String path, Map<String, dynamic>? params) {
return [
const AppPage(
key: ValueKey('home'),
title: 'Home',
child: HomePage(title: 'Home Page',),
),
];
}
@override
String getRoute() {
return route;
}
}
- 添加一个首页(这是一个计数器应用页面):
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<HomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<HomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // 这个尾部逗号使自动格式化更美观。
);
}
}
- 运行应用。
守卫
该插件还支持守卫:
class AppNavigationManager extends AbstractAppNavigationManager {
final AbstractAppRouter routerDelegate;
AppNavigationManager(this.routerDelegate) : super(routerDelegate);
@override
List<AppNavigationGuard> guards = [
AppNavigationGuard(
guardExcludePattern: r"(/project_manager_login|/technician_login|/app_settings|/device_assignment)$",
guardPattern: r"/*",
guard: (path) {
final appCubit = AppDi().appCubit();
if (appCubit.state.appToken.isEmpty && appCubit.state.authToken.isEmpty) {
return ProjectManagerLoginLocation();
} else if (appCubit.state.appToken.isNotEmpty && appCubit.state.authToken.isEmpty) {
return TechnicianLoginLocation();
} else if (appCubit.state.appToken.isEmpty && appCubit.state.authToken.isNotEmpty) {
return DeviceAssignmentLocation();
} else {
return null;
}
},
),
];
@override
List<AppLocation> get locations => [
ProjectManagerLoginLocation(),
DeviceAssignmentLocation(),
TechnicianLoginLocation(),
AppSettingsLocation(),
HomeLocation(),
];
}
使用方法
该插件使用 BuildContext
扩展,以下是示例:
你可以通过以下方式导航到页面:
context.hopNamed('/home');
context.hopReplacementNamed('/home');
你可以将参数与路径关联起来:
context.hopNamed('/home', {"id": 1, "name": "John"});
返回上一个页面:
context.hopBack();
context.hopBack(result); // 返回一个结果
关闭对话框或抽屉:
Navigator.of(context).pop();
你可以等待从页面返回的结果:
int code = await context.hopNamed('/get_some_code');
更多关于Flutter插件hopper的特性与使用指南的实战教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复
更多关于Flutter插件hopper的特性与使用指南的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter开发中,如果你遇到“功能未定义插件hopper”的问题,可能是指你尝试使用了一个名为“hopper”的插件,但该插件在项目中未被正确引入或定义。以下是探索和解决此问题的步骤:
1. 确认插件名称和用途
- 首先,确认你使用的插件名称是否为“hopper”。
- 检查插件的用途,了解它是否是一个官方插件、第三方插件,或者是你自定义的插件。
2. 检查 pubspec.yaml
文件
- 打开项目的
pubspec.yaml
文件,查看是否已正确引入“hopper”插件。 - 示例:
dependencies: flutter: sdk: flutter hopper: ^1.0.0 # 确保版本号正确
- 如果没有引入,请添加插件并运行
flutter pub get
以安装依赖。
3. 检查插件是否存在
- 访问 pub.dev 搜索“hopper”,确认该插件是否存在。
- 如果不存在,可能是插件名称错误,或者你需要使用其他替代插件。
4. 检查插件导入
- 在代码中检查是否正确导入了插件。示例:
import 'package:hopper/hopper.dart';
- 如果导入路径错误,可能会导致“未定义”的问题。
5. 检查插件初始化
- 如果插件需要在
main.dart
或其他地方进行初始化,请确保已正确调用初始化方法。 - 示例:
void main() { Hopper.initialize(); runApp(MyApp()); }
6. 检查插件版本兼容性
- 确保插件的版本与当前 Flutter SDK 版本兼容。
- 如果不兼容,尝试升级或降级插件版本。
7. 清理和重建项目
- 运行以下命令清理和重建项目:
flutter clean flutter pub get flutter run