Flutter 新聞客戶端 - 08 路由管理 auto_route

會煮咖啡的貓發表於2020-06-24

Flutter 新聞客戶端 - 08 路由管理 auto_route

B站視訊

www.bilibili.com/video/BV1xf…

本節目標

  • 安裝外掛
  • 路由定義
  • 自動生成路由控制類
  • 轉場動畫
  • 登入檢查中介軟體
  • 帶引數傳遞
  • 獲取返回值

正文

一些優秀的路由外掛

  • fluro

    前端的使用體驗

    router.navigateTo(context, "/users/1234", transition: TransitionType.fadeIn);

  • flutter_modular

    功能強大的路由管理:中介軟體、懶載入、狀態管理、動態路由、分組路由、動畫、返回值、命名路由

  • auto_route

    設計精簡、低耦合其它功能

    功能:中介軟體、自動生成路由程式碼、動態路由、動畫、返回值、命名路由

安裝外掛

  • 官網

pub.flutter-io.cn/packages/au…

  • pubspec.yaml
dependencies:
  flutter:
    sdk: flutter

  # 路由管理
  auto_route: ^0.4.4

dev_dependencies:
  flutter_test:
    sdk: flutter

  # 路由生成
  auto_route_generator: ^0.4.4
  build_runner:
複製程式碼

路由定義

  • lib/common/router/router.dart
@MaterialAutoRouter()
class $AppRouter {
  @initial
  IndexPage indexPageRoute;

  WelcomePage welcomePageRoute;

  SignInPage signInPageRoute;

  SignUpPage signUpPageRoute;

  ApplicationPage applicationPageRoute;

  DetailsPage detailsPageRoute;
}
複製程式碼

注意 $ 符號

自動生成路由控制類

  • 執行命令
flutter packages pub run build_runner build
複製程式碼
  • 自動生成 lib/common/router/router.gr.dart
// GENERATED CODE - DO NOT MODIFY BY HAND

// **************************************************************************
// AutoRouteGenerator
// **************************************************************************

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:auto_route/auto_route.dart';
import 'package:flutter_ducafecat_news/pages/index/index.dart';
import 'package:flutter_ducafecat_news/pages/welcome/welcome.dart';
import 'package:flutter_ducafecat_news/pages/sign_in/sign_in.dart';
import 'package:flutter_ducafecat_news/pages/sign_up/sign_up.dart';
import 'package:flutter_ducafecat_news/pages/application/application.dart';
import 'package:flutter_ducafecat_news/common/router/auth_grard.dart';
import 'package:flutter_ducafecat_news/pages/details/details.dart';

abstract class Routes {
  static const indexPageRoute = '/';
  static const welcomePageRoute = '/welcome-page-route';
  static const signInPageRoute = '/sign-in-page-route';
  static const signUpPageRoute = '/sign-up-page-route';
  static const applicationPageRoute = '/application-page-route';
  static const detailsPageRoute = '/details-page-route';
}

class AppRouter extends RouterBase {
  @override
  Map<String, List<Type>> get guardedRoutes => {
        Routes.applicationPageRoute: [AuthGuard],
        Routes.detailsPageRoute: [AuthGuard],
      };

  //This will probably be removed in future versions
  //you should call ExtendedNavigator.ofRouter<Router>() directly
  static ExtendedNavigatorState get navigator =>
      ExtendedNavigator.ofRouter<AppRouter>();

  @override
  Route<dynamic> onGenerateRoute(RouteSettings settings) {
    final args = settings.arguments;
    switch (settings.name) {
      case Routes.indexPageRoute:
        if (hasInvalidArgs<IndexPageArguments>(args)) {
          return misTypedArgsRoute<IndexPageArguments>(args);
        }
        final typedArgs = args as IndexPageArguments ?? IndexPageArguments();
        return MaterialPageRoute<dynamic>(
          builder: (_) => IndexPage(key: typedArgs.key),
          settings: settings,
        );
      case Routes.welcomePageRoute:
        if (hasInvalidArgs<WelcomePageArguments>(args)) {
          return misTypedArgsRoute<WelcomePageArguments>(args);
        }
        final typedArgs =
            args as WelcomePageArguments ?? WelcomePageArguments();
        return MaterialPageRoute<dynamic>(
          builder: (_) => WelcomePage(key: typedArgs.key),
          settings: settings,
        );
      case Routes.signInPageRoute:
        if (hasInvalidArgs<SignInPageArguments>(args)) {
          return misTypedArgsRoute<SignInPageArguments>(args);
        }
        final typedArgs = args as SignInPageArguments ?? SignInPageArguments();
        return MaterialPageRoute<dynamic>(
          builder: (_) => SignInPage(key: typedArgs.key),
          settings: settings,
        );
      case Routes.signUpPageRoute:
        if (hasInvalidArgs<SignUpPageArguments>(args)) {
          return misTypedArgsRoute<SignUpPageArguments>(args);
        }
        final typedArgs = args as SignUpPageArguments ?? SignUpPageArguments();
        return MaterialPageRoute<dynamic>(
          builder: (_) => SignUpPage(key: typedArgs.key),
          settings: settings,
        );
      case Routes.applicationPageRoute:
        if (hasInvalidArgs<ApplicationPageArguments>(args)) {
          return misTypedArgsRoute<ApplicationPageArguments>(args);
        }
        final typedArgs =
            args as ApplicationPageArguments ?? ApplicationPageArguments();
        return MaterialPageRoute<dynamic>(
          builder: (_) => ApplicationPage(key: typedArgs.key),
          settings: settings,
        );
      case Routes.detailsPageRoute:
        if (hasInvalidArgs<DetailsPageArguments>(args)) {
          return misTypedArgsRoute<DetailsPageArguments>(args);
        }
        final typedArgs =
            args as DetailsPageArguments ?? DetailsPageArguments();
        return MaterialPageRoute<dynamic>(
          builder: (_) => DetailsPage(key: typedArgs.key),
          settings: settings,
        );
      default:
        return unknownRoutePage(settings.name);
    }
  }
}

//**************************************************************************
// Arguments holder classes
//***************************************************************************

//IndexPage arguments holder class
class IndexPageArguments {
  final Key key;
  IndexPageArguments({this.key});
}

//WelcomePage arguments holder class
class WelcomePageArguments {
  final Key key;
  WelcomePageArguments({this.key});
}

//SignInPage arguments holder class
class SignInPageArguments {
  final Key key;
  SignInPageArguments({this.key});
}

//SignUpPage arguments holder class
class SignUpPageArguments {
  final Key key;
  SignUpPageArguments({this.key});
}

//ApplicationPage arguments holder class
class ApplicationPageArguments {
  final Key key;
  ApplicationPageArguments({this.key});
}

//DetailsPage arguments holder class
class DetailsPageArguments {
  final Key key;
  DetailsPageArguments({this.key});
}

複製程式碼

路由跳轉

  • 方式 1:帶 context 方式
ExtendedNavigator.of(context).pushNamed(Routes.signUpPageRoute);
複製程式碼
  • 方式 2:不帶 context 方式
ExtendedNavigator.ofRouter<AppRouter>().pushNamed(Routes.signUpPageRoute);
複製程式碼
  • 方式 3:如果你只有一個導航
ExtenedNavigator.rootNavigator.pushNamed(Routes.signUpPageRoute);
複製程式碼

轉場動畫

  • lib/common/router/router.dart
Widget zoomInTransition(BuildContext context, Animation<double> animation,
    Animation<double> secondaryAnimation, Widget child) {
  // you get an animation object and a widget
  // make your own transition
  return ScaleTransition(scale: animation, child: child);
}

@MaterialAutoRouter()
class $AppRouter {
  ...

  @CustomRoute(transitionsBuilder: zoomInTransition)
  ApplicationPage applicationPageRoute;
}
複製程式碼
  • 重新生成
flutter packages pub run build_runner build
複製程式碼

登入檢查中介軟體

  • 建立 lib/common/router/auth_grard.dart
import 'package:auto_route/auto_route.dart';
import 'package:flutter_ducafecat_news/common/router/router.gr.dart';
import 'package:flutter_ducafecat_news/common/utils/utils.dart';

class AuthGuard extends RouteGuard {
  @override
  Future<bool> canNavigate(ExtendedNavigatorState navigator, String routeName,
      Object arguments) async {
    var isAuth = await isAuthenticated();
    if (isAuth == false) {
      ExtendedNavigator.rootNavigator.pushNamed(Routes.signInPageRoute);
    }

    return isAuth;
  }
}
複製程式碼
  • 註冊 lib/main.dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'ducafecat.tech',
      debugShowCheckedModeBanner: false,
      builder: ExtendedNavigator<AppRouter>(
        initialRoute: Routes.indexPageRoute,
        router: AppRouter(),
        guards: [AuthGuard()],
      ),
    );
  }
}
複製程式碼
  • 定義 lib/common/router/router.dart
@MaterialAutoRouter()
class $AppRouter {
  ...

  @GuardedBy([AuthGuard])
  @CustomRoute(transitionsBuilder: zoomInTransition)
  ApplicationPage applicationPageRoute;
}
複製程式碼
  • 重新生成
flutter packages pub run build_runner build
複製程式碼

引數傳遞

  • 設定初始引數 lib/pages/details/details.dart
class DetailsPage extends StatefulWidget {
  final String cid;
  DetailsPage({Key key, this.cid}) : super(key: key);
複製程式碼
  • 定義 lib/common/router/router.dart
@MaterialAutoRouter(generateNavigationHelperExtension: true)
class $AppRouter {
  ...
複製程式碼
  • 重新生成
flutter packages pub run build_runner build
複製程式碼
  • lib/common/router/router.gr.dart
//DetailsPage arguments holder class
class DetailsPageArguments {
  final Key key;
  final String cid;
  DetailsPageArguments({this.key, this.cid});
}
複製程式碼
  • 導航引數
ExtendedNavigator.rootNavigator.pushDetailsPageRoute(cid: '123');
複製程式碼
  • 獲取返回值
    ExtendedNavigator.rootNavigator
        .pushNamed(Routes.signUpPageRoute)
        .then((onValue) {
      print(onValue);
    });
複製程式碼

資源

視訊

藍湖設計稿(加微信給授權 ducafecat)

lanhuapp.com/url/lYuz1 密碼: gSKl

藍湖現在收費了,所以檢視標記還請自己上傳 xd 設計稿 商業設計稿檔案不好直接分享, 可以加微信聯絡 ducafecat

YAPI 介面管理

yapi.demo.qunar.com/

程式碼

github.com/ducafecat/f…

參考

pub.flutter-io.cn/packages/au…

VSCode 外掛

相關文章