Flutter导航管理插件riverpod_navigation的使用

Flutter导航管理插件riverpod_navigation的使用

管理Flutter导航可以使用riverpod插件。本文将详细介绍如何使用riverpod_navigation插件来管理应用的导航。

使用

引导

替换你的根ProviderScope为一个带有路由层次结构的RiverpodNavigation小部件,并给定提供的delegateparserMaterialApp.router工厂。

final routes = RouteDefinition(
    template: UriTemplate.parse('/'),
    builder: (context, entry) => MaterialPage(
      child: HomeLayout(),
    ),
    next: [
      RouteDefinition(
        template: UriTemplate.parse('/articles/:id'),
        builder: (context, entry) => MaterialPage(
          child: ArticleLayout(
            id: entry.parameters['id']!,
          ),
        ),
      ),
    ],
);

return RiverpodNavigation( // 替换你的根ProviderScope
  routes: routes,
  builder: (context, delegate, parser) => MaterialApp.router(
    title: 'Flutter Demo',
    routerDelegate: delegate,
    routeInformationParser: parser,
  ),
);

导航

从Provider访问

暴露了一个navigationProvider,可以用来读取当前的导航状态。

要访问允许各种操作的基础通知器,可以使用navigationProvider.notifier

final myProvider = Provider<MyState>((ref) {
    final navigation = ref.watch(navigationProvider.notifier);
    return MyState(
        navigateToArticles: () {
            navigation.navigate(Uri.parse('/articles'))
        },
        pop: () {
            navigation.pop();
        }
    );
},
);

从BuildContext访问

可以通过BuildContextnavigation扩展方法访问通知器。

[@override](/user/override)
Widget build(BuildContext context) {
    return TextButton(
        child: Text('Articles'),
        onPressed: () {
            context.navigation.navigate(Uri.parse('/articles'))
        }
    );
}

返回行为

为了自定义返回时的弹出行为,可以在RiverpodNavigation实例中提供一个PopBehavior回调。结果表示当前弹出动作是否应该更新、取消或采用默认行为(即简单地用父路由替换当前路由)。

RiverpodNavigation(
    popBehaviour: (notifier, stack) {
        if (stack.lastRoute?.key == Key('share-article')) {
          return PopResult.update(Uri.parse('/'));
        }
        return PopResult.auto();
      },
    // ...
)

URI重写

可以在URI被路由器处理之前对其进行修改,通过提供uriRewriter属性。这可以用于重定向或规范化URI。

RiverpodNavigation(
    uriRewriter: (notifier, uri) {
        if (uri == Uri.parse('/home')) {
            return Uri.parse('/');
        }
        const publicPrefix = 'https://example.com';
        final stringUri = uri.toString();
        if (stringUri.startsWith(publicPrefix)) {
            return Uri.parse(stringUri.substring(publicPrefix.length));
        }
        return uri;
    },
    // ...
);

完整示例Demo

以下是一个完整的示例Demo,展示了如何使用riverpod_navigation插件。

import 'package:example/layouts/about.dart';
import 'package:example/layouts/article.dart';
import 'package:example/layouts/home.dart';
import 'package:example/layouts/tabs/all_articles.dart';
import 'package:example/layouts/tabs/shop.dart';
import 'package:example/layouts/tabs/update_profile.dart';
import 'package:example/layouts/tabs/user.dart';
import 'package:flutter/material.dart';
import 'package:riverpod_navigation/riverpod_navigation.dart';

import 'layouts/share.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    final routes = RouteDefinition(
      key: Key('Home'),
      template: UriTemplate.parse('/'),
      builder: (context, entry, tabs, activeTab) => MaterialPage(
        child: HomeLayout(
          activeTab: activeTab,
          tabs: tabs,
        ),
      ),
      tabs: [
        RouteDefinition(
          template: UriTemplate.parse('/all-articles'),
          builder: (context, entry, tabs, activeTab) => MaterialPage(
            child: AllArticlesLayout(),
          ),
        ),
        RouteDefinition(
          template: UriTemplate.parse('/shop'),
          builder: (context, entry, tabs, activeTab) => MaterialPage(
            child: ShopLayout(),
          ),
        ),
        RouteDefinition(
          template: UriTemplate.parse('/user'),
          builder: (context, entry, tabs, activeTab) => MaterialPage(
            child: UserLayout(),
          ),
          next: [
            RouteDefinition(
              template: UriTemplate.parse('/update-profile'),
              builder: (context, entry, tabs, activeTab) => MaterialPage(
                child: UpdateProfileLayout(),
              ),
            ),
          ],
        ),
      ],
      next: [
        RouteDefinition(
          template: UriTemplate.parse('/articles/:id'),
          builder: (context, entry, tabs, activeTab) => MaterialPage(
            child: ArticleLayout(
              id: entry.parameter('id'),
            ),
          ),
          next: [
            RouteDefinition(
              template: UriTemplate.parse('/share'),
              key: Key('share'),
              builder: (context, entry, tabs, activeTab) => MaterialPage(
                child: ShareLayout(
                  articleId: entry.parameter('id'),
                ),
              ),
            ),
          ],
        ),
        RouteDefinition(
          template: UriTemplate.parse('/about'),
          builder: (context, entry, tabs, activeTab) => MaterialPage(
            child: AboutLayout(),
          ),
        ),
      ],
    );

    return RiverpodNavigation(
      routes: routes,
      uriRewriter: (notifier, uri) {
        const publicPrefix = 'https://example.com';
        final stringUri = uri.toString();
        if (stringUri.startsWith(publicPrefix)) {
          return Uri.parse(stringUri.substring(publicPrefix.length));
        }
        return uri;
      },
      popBehaviour: (notifier, stack) {
        if (stack.lastRoute?.key == Key('share')) {
          return PopResult.update(Uri.parse('/'));
        }
        return PopResult.auto();
      },
      builder: (context, delegate, parser) => MaterialApp.router(
        title: 'Flutter Demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        routerDelegate: delegate,
        routeInformationParser: parser,
      ),
    );
  }
}

更多关于Flutter导航管理插件riverpod_navigation的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter导航管理插件riverpod_navigation的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


riverpod_navigation 是一个结合了 Riverpod 状态管理和 Flutter 导航功能的插件,旨在简化应用中的路由管理和状态共享。它提供了一种声明式的方式来处理导航,并且能够与 Riverpod 无缝集成。

以下是使用 riverpod_navigation 的基本步骤和一个简单的示例:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 riverpod_navigation 依赖:

dependencies:
  flutter:
    sdk: flutter
  riverpod: ^2.0.0
  riverpod_navigation: ^0.1.0

然后运行 flutter pub get 来安装依赖。

2. 创建路由状态提供者

使用 riverpod_navigationNavigationProvider 来管理路由状态。你可以创建一个全局的 Provider 来管理导航栈。

import 'package:riverpod/riverpod.dart';
import 'package:riverpod_navigation/riverpod_navigation.dart';

final navigationProvider = StateNotifierProvider<NavigationNotifier, NavigationState>((ref) {
  return NavigationNotifier();
});

3. 定义路由

在你的应用中定义路由。你可以使用 MaterialPageRoute 或其他类型的路由。

import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
 title: Text('Home'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            context.read(navigationProvider.notifier).push('/details');
          },
          child: Text('Go to Details'),
        ),
      ),
    );
  }
}

class DetailsPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
 title: Text('Details'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            context.read(navigationProvider.notifier).pop();
          },
          child: Text('Go back'),
        ),
      ),
    );
  }
}

4. 配置导航

MaterialApp 中使用 riverpod_navigationNavigation 组件来管理导航。

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_navigation/riverpod_navigation.dart';

void main() {
  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Navigation(
        provider: navigationProvider,
        routes: {
          '/': (context) => HomePage(),
          '/details': (context) => DetailsPage(),
        },
      ),
    );
  }
}

5. 使用导航

在你的应用中使用 context.read(navigationProvider.notifier) 来执行导航操作,例如 pushpop

onPressed: () {
  context.read(navigationProvider.notifier).push('/details');
},

6. 处理深链接

riverpod_navigation 也支持处理深链接。你可以在 NavigationNotifier 中定义深链接的处理逻辑。

final navigationProvider = StateNotifierProvider<NavigationNotifier, NavigationState>((ref) {
  return NavigationNotifier()..handleDeepLink('/initialPath');
});
回到顶部