Flutter Getx 01 - 路由、中介軟體、鑑權、傳值、跳轉

會煮咖啡的貓發表於2021-04-05

Getx

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

vscode 外掛

Android Studio/Intellij 外掛

本節目標

  • GetPage 物件
  • 路由層級控制
  • 路由中介軟體、鑑權
  • 404 處理
  • 路由跳轉、替換、清除
  • 路由傳值、返回值
  • 路由轉場動畫

開發環境

  • Flutter 2.1.0-12.1.pre
  • Dart 2.13.0
  • get: ^3.26.0

參考

視訊

www.bilibili.com/video/BV1yU…

程式碼

github.com/ducafecat/g…

正文

初始 getx 專案

  • pubspec.yaml
dependencies:
  ...
  get: ^3.26.0
複製程式碼
  • lib/pages/home/index.dart
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class HomeView extends StatelessWidget {
  const HomeView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("首頁"),
      ),
      body: ListView(
        children: [
          // 路由&導航
          Divider(),

        ],
      ),
    );
  }
}
複製程式碼
  • lib/common/routes/app_routes.dart
part of 'app_pages.dart';

abstract class AppRoutes {
  static const Home = '/home';
}
複製程式碼
  • lib/common/routes/app_pages.dart
import 'package:get/get.dart';

part 'app_routes.dart';

class AppPages {
  static const INITIAL = AppRoutes.Home;

  static final routes = [
    GetPage(
      name: AppRoutes.Home,
      page: () => HomeView(),
    ),
  ];
}
複製程式碼
  • lib/main.dart
Future<void> main() async {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      debugShowCheckedModeBanner: false,
      initialRoute: AppPages.INITIAL,
      getPages: AppPages.routes,
    );
  }
}
複製程式碼

編寫 GetPage 定義

  • lib/pages/list/index.dart
class ListView extends StatelessWidget {
  const ListView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("列表頁"),
      ),
    );
  }
}
複製程式碼
  • lib/pages/list_detail/index.dart
class DetailView extends StatelessWidget {
  const DetailView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("詳情頁"),
      ),
      body: ListView(
        children: [
          ListTile(
            title: Text("導航-返回"),
            subtitle: Text('Get.back()'),
            onTap: () => Get.back(),
          ),
        ],
      ),
    );
  }
}
複製程式碼
  • lib/common/routes/app_routes.dart
abstract class AppRoutes {
  static const Home = '/home';
  static const List = '/list';
  static const Detail = '/detail';
複製程式碼
  • lib/common/routes/app_pages.dart
    GetPage(
      name: AppRoutes.Home,
      page: () => HomeView(),
      children: [
        GetPage(
          name: AppRoutes.List,
          page: () => ListView(),
          children: [
            GetPage(
              name: AppRoutes.Detail,
              page: () => DetailView(),
            ),
          ],
        ),
      ],
    ),
複製程式碼

導航操作 命名、檢視物件

  • lib/pages/home/index.dart
  ListTile(
    title: Text("導航-命名路由 home > list"),
    subtitle: Text('Get.toNamed("/home/list")'),
    onTap: () => Get.toNamed("/home/list"),
  ),
  ListTile(
    title: Text("導航-命名路由 home > list > detail"),
    subtitle: Text('Get.toNamed("/home/list/detail")'),
    onTap: () => Get.toNamed("/home/list/detail"),
  ),
  ListTile(
    title: Text("導航-類物件"),
    subtitle: Text("Get.to(DetailView())"),
    onTap: () => Get.to(DetailView()),
  ),
複製程式碼

導航-清除上一個

  • lib/pages/home/index.dart
  ListTile(
    title: Text("導航-清除上一個"),
    subtitle: Text("Get.off(DetailView())"),
    onTap: () => Get.off(DetailView()),
  ),
複製程式碼

導航-清除所有

  • lib/pages/home/index.dart
  ListTile(
    title: Text("導航-清除所有"),
    subtitle: Text("Get.offAll(DetailView())"),
    onTap: () => Get.offAll(DetailView()),
  ),
複製程式碼

導航-arguments 傳值+返回值

  • lib/pages/home/index.dart
  ListTile(
    title: Text("導航-arguments傳值+返回值"),
    subtitle: Text(
        'Get.toNamed("/home/list/detail", arguments: {"id": 999})'),
    onTap: () async {
      var result = await Get.toNamed("/home/list/detail",
          arguments: {"id": 999});
      Get.snackbar("返回值", "success -> " + result["success"].toString());
    },
  ),
複製程式碼
  • lib/pages/list_detail/index.dart
  _buildBackListTileRow(Map? val) {
    return val == null
        ? Container()
        : ListTile(
            title: Text("傳值 id = " + val["id"].toString()),
            subtitle: Text('Get.back(result: {"success": true}'),
            onTap: () => Get.back(result: {"success": true}),
          );
  }

  @override
  Widget build(BuildContext context) {
    final details = Get.arguments as Map;
    final parameters = Get.parameters;

    return Scaffold(
      appBar: AppBar(
        title: Text("詳情頁"),
      ),
      body: ListView(
        children: [
          ListTile(
            title: Text("導航-返回"),
            subtitle: Text('Get.back()'),
            onTap: () => Get.back(),
          ),
          _buildBackListTileRow(details),
          _buildBackListTileRow(parameters),
        ],
      ),
    );
  }
複製程式碼

導航-parameters 傳值+返回值

  • lib/pages/home/index.dart
  ListTile(
    title: Text("導航-parameters傳值+返回值"),
    subtitle: Text('Get.toNamed("/home/list/detail?id=666")'),
    onTap: () async {
      var result = await Get.toNamed("/home/list/detail?id=666");
      Get.snackbar("返回值", "success -> " + result["success"].toString());
    },
  ),
複製程式碼
  • lib/pages/list_detail/index.dart
  @override
  Widget build(BuildContext context) {
    final parameters = Get.parameters;
複製程式碼

導航-引數傳值+返回值

  • lib/common/routes/app_routes.dart
  static const Detail_ID = '/detail/:id';
複製程式碼
  • lib/common/routes/app_pages.dart
  ...
  GetPage(
    name: AppRoutes.Detail_ID,
    page: () => DetailView(),
  ),
複製程式碼
  • lib/pages/home/index.dart
  ListTile(
    title: Text("導航-引數傳值+返回值"),
    subtitle: Text('Get.toNamed("/home/list/detail/777")'),
    onTap: () async {
      var result = await Get.toNamed("/home/list/detail/777");
      Get.snackbar("返回值", "success -> " + result["success"].toString());
    },
  ),
複製程式碼

導航-not found

  • lib/pages/notfound/index.dart
class NotfoundView extends StatelessWidget {
  const NotfoundView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("路由沒有找到"),
      ),
      body: ListTile(
        title: Text("返回首頁"),
        subtitle: Text('Get.offAllNamed(AppRoutes.Home)'),
        onTap: () => Get.offAllNamed(AppRoutes.Home),
      ),
    );
  }
}
複製程式碼
  • lib/common/routes/app_routes.dart
  static const NotFound = '/notfound';
複製程式碼
  • lib/common/routes/app_pages.dart
  static final unknownRoute = GetPage(
    name: AppRoutes.NotFound,
    page: () => NotfoundView(),
  );
複製程式碼
  • lib/main.dart
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      ...
      unknownRoute: AppPages.unknownRoute,
    );
  }
複製程式碼

導航-中介軟體-認證 Auth

  • lib/pages/login/index.dart
class LoginView extends StatelessWidget {
  const LoginView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("登入"),
      ),
      body: ListTile(
        title: Text("返回首頁"),
        subtitle: Text('Get.offAllNamed(AppRoutes.Home)'),
        onTap: () => Get.offAllNamed(AppRoutes.Home),
      ),
    );
  }
}
複製程式碼
  • lib/pages/my/index.dart
class MyView extends StatelessWidget {
  const MyView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("我的"),
      ),
      body: ListTile(
        title: Text("返回首頁"),
        subtitle: Text('Get.offAllNamed(AppRoutes.Home)'),
        onTap: () => Get.offAllNamed(AppRoutes.Home),
      ),
    );
  }
}
複製程式碼
  • lib/common/routes/app_routes.dart
  static const Login = '/login';
  static const My = '/my';
複製程式碼
  • lib/common/middleware/router_auth.dart
class RouteAuthMiddleware extends GetMiddleware {
  @override
  int priority = 0;

  RouteAuthMiddleware({required this.priority});

  @override
  RouteSettings? redirect(String route) {
    Future.delayed(Duration(seconds: 1), () => Get.snackbar("提示", "請先登入APP"));
    return RouteSettings(name: AppRoutes.Login);
  }
}
複製程式碼
  • lib/common/routes/app_pages.dart
    // 白名單
    GetPage(
      name: AppRoutes.Login,
      page: () => LoginView(),
    ),

    GetPage(
      name: AppRoutes.My,
      page: () => MyView(),
      middlewares: [
        RouteAuthMiddleware(priority: 1),
      ],
    ),
複製程式碼
  • lib/pages/home/index.dart
  ListTile(
    title: Text("導航-中介軟體-認證Auth"),
    subtitle: Text('Get.toNamed(AppRoutes.My)'),
    onTap: () => Get.toNamed(AppRoutes.My),
  ),
複製程式碼

Transition 轉場動畫

  • lib/common/routes/app_pages.dart
  GetPage(
    name: AppRoutes.Detail_ID,
    page: () => DetailView(),
    transition: Transition.downToUp,
  ),
複製程式碼

© 貓哥

ducafecat.tech

ducafecat.gitee.io

相關文章