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天就完成了编写。


入门指南

简单的应用程序,只有一个首页

  1. 将插件添加到你的 pubspec.yaml 文件中:
dependencies:
  flutter:
    sdk: flutter

  hopper: ^1.2.0
  1. 创建你的 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,
    );
  }
}
  1. 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;
  }
}
  1. 添加一个首页(这是一个计数器应用页面):
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),
      ), // 这个尾部逗号使自动格式化更美观。
    );
  }
}
  1. 运行应用。

守卫

该插件还支持守卫:

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
回到顶部