likes
comments
collection
share

二、Flutter必学!Getx路由管理

作者站长头像
站长
· 阅读数 32

什么是 GetX?

一个简单、高效、强大的管理状态、路由管理库

学习目标

  • 掌握使用GetX管理路由
  • 掌握使用GetX路由的中间件
  • 学会配置路由

GetX路由管理优点

  • 使用简洁、逻辑清晰(Controller)
  • 功能强大,多种使用形态

安装

先安装get依赖到你的pubspec.yaml文件中

dependencies:
	get:

一、路由的用法

使用路由之前需要把MaterialApp换成GetMaterialApp,这十分重要!

// MaterialApp(  之前是这样
GetMaterialApp(
  home: MyHome(),
)

1.普通路由导航

1.1 to进入新页面

从当前页面进入到一个新页面,to接收一个页面组件

Get.to(NextScreen());

1.2 back回退操作

通常会用Navigator.pop(context)关闭的东西。

使用场景: 关闭DialogsSnackBars或者退出当前页面。

Get.back();

1.3 off类似于replace操作

它会替拿当新页面换掉当前页面,并且新页面左上角没有返回按钮,

使用场景: 登录页、SplashScreens之类的

Get.off(NextScreen());

1.4 offAll清空历史路由

该方法会清空我们之前打开过的页面,只留下新的页面

使用场景: 购物车、投票之类的

Get.offAll(NextScreen());

1.5 接收新返回信息

var data = await Get.to(Payment());

2.别名路由导航

你不必有太多的学习压力,别名路由十分简单

// toNamed 导航到下一个页面
Get.toNamed("/NextScreen");

// 浏览并删除前一个页面
Get.offNamed("/NextScreen");

// 浏览并删除所有以前的页面
Get.offAllNamed("/NextScreen");

3.路由传参数

有3种传递参数的方法:

  • arguments传参
  • 问号传参(跟URL地址一样)
  • 动态路由(/:xxx

3.1 arguments传参

发送任何参数都可以接收,不论是什么类型!甚至是类的实例!

Get.toNamed("/NextScreen", arguments: '这是一个字符串参数');

在页面类或控制器上接收:

print(Get.arguments); // out: 这是一个字符串参数

3.2问号传参

只能接收字符串

Get.offAllNamed("/NextScreen?device=phone&id=111&name=liang");

通过Get.parameters获取值

print(Get.parameters['id']); // out: 111
print(Get.parameters['name']); // out: liang
void main() {
  runApp(
    GetMaterialApp(
      initialRoute: '/',
      getPages: [
        GetPage(
          name: '/',
          page: () => MyHomePage(),
        ),
        GetPage(
          name: '/profile/',
          page: () => MyProfile(),
        ),
        GetPage(
          name: '/profile/:user',
          page: () => UserProfile(),
        ),
      ],
    )
  );
}

3.3动态路由

咱们在配置表中配置动态路由,他是通过Get.parameters接收

void main() {
  runApp(
    GetMaterialApp(
      initialRoute: '/',
      getPages: [
      GetPage(
        name: '/',
        page: () => MyHomePage(),
      ),
      GetPage(
        name: '/profile/', // 没值匹配就写 / 在后面
        page: () => MyProfile(),
      ),
      GetPage(
        name: '/profile/:user', // 如果有值 /:xxx 在后面
        page: () => UserProfile(),
      ),
      GetPage(
        name: '/third',
        page: () => Third(),
        transition: Transition.cupertino  
      ),
     ],
    )
  );
}

发送别名路由数据:

Get.toNamed("/profile/34954");


// 在第二个页面上,通过参数获取数据
print(Get.parameters['user']);
// out: 34954

混合发送参数:

Get.toNamed("/profile/34954?flag=true");

// 在第二个页面上,通过参数获取数据
print(Get.parameters['user']);
print(Get.parameters['flag']);
// out: 34954 true

4.路由中间件

除了可以监听路由外,还可以监听每个页面上的SnackBars DialogsBottomsheets

有两种方式可以实现中间件:

  • GetMaterialApproutingCallback
  • MaterialAppnavigatorObservers(相对麻烦)

中间件:字面意思就是在中间处理一些事件

4.1routingCallback

通过监听Get事件触发回调,我们可以基于GetMaterialApproutingCallback参数实现。

GetMaterialApp(
  routingCallback: (routing) {
    if(routing.current == '/user') {
      openAds();
    }
  }
)

4.2navigatorObservers

如果没有使用GetMaterialApp,那么可以使用API来附加Middleware观察器。

void main() {
  runApp(
    MaterialApp(
      onGenerateRoute: Router.generateRoute,
      initialRoute: "/",
      navigatorKey: Get.key,
      navigatorObservers: [ // 基于这个来观察路由变化
        GetObserver(MiddleWare.observer), // HERE !!!
      ],
    ),
  );
}

4.2.1创建一个MiddleWare类

class MiddleWare {
  static observer(Routing routing) {
    if (routing.current == '/second' && !routing.isSnackbar) {
      Get.snackbar("Hi", "You are on second route");
    } else if (routing.current =='/third'){
      print('last route called');
    }
  }
}

二、GetMaterialApp的常用配置

使用GetMaterialApp定义路由。

void main() {
  runApp(
    GetMaterialApp(
      // 初始路径
      initialRoute: '/',
      
      // 404页面
      unknownRoute: GetPage(name: '/notfound', page: () => UnknownRoutePage()),

      // 中间件
      routingCallback: (routing) {
        if(routing.current == '/user') {
          openAds();
        }
      },
      
      // 路由配置表
      getPages: [
        GetPage(name: '/', page: () => MyHomePage()),
        GetPage(name: '/second', page: () => Second()),
      ],
    )
  );
}

三、免context导航

SnackBars

以前你可能需要这样去写一个SnackBars功能:

final snackBar = SnackBar(
  content: Text('Hi!'),
  action: SnackBarAction(
    label: 'I am a old and ugly snackbar :(',
    onPressed: (){}
  ),
);
// 在小组件树中找到脚手架并使用它显示一个SnackBars。
Scaffold.of(context).showSnackBar(snackBar);

但是使用Get后可以随处使用它!

Get.snackbar('Hi', 'i am a modern snackbar');

// 定制你的需求,随处可使用
Get.snackbar(
  "Hey i'm a Get SnackBar!", // title
  "It's unbelievable! I'm using SnackBar without context, without boilerplate, without Scaffold, it is something truly amazing!", // message
  icon: Icon(Icons.alarm),
  shouldIconPulse: true,
  onTap:(){},
  barBlur: 20,
  isDismissible: true,
  duration: Duration(seconds: 3),
);

Dialog

// 定制一个 Dialog
Get.dialog(YourDialogWidget());

打开默认Dialogs

Get.defaultDialog(
  onConfirm: () => print("Ok"),
  middleText: "Dialog made in 3 lines of code"
);

BottomSheets

Get.bottomSheet(
  Container(
    child: Wrap(
      children: <Widget>[
        ListTile(
          leading: Icon(Icons.music_note),
          title: Text('Music'),
          onTap: () {}
        ),
        ListTile(
          leading: Icon(Icons.videocam),
          title: Text('Video'),
          onTap: () {},
        ),
      ],
    ),
  )
);

四、嵌套导航

Get的路由嵌套非常简单,不需要context而是通过id寻找导航栈

Navigator(
  key: Get.nestedKey(1), // 创建一个key
  initialRoute: '/',
  onGenerateRoute: (settings) {
    if (settings.name == '/') {
      return GetPageRoute(
        page: () => Scaffold(
          appBar: AppBar(
            title: Text("Main"),
          ),
          body: Center(
            child: TextButton(
              color: Colors.blue,
              onPressed: () {
                Get.toNamed('/second', id:1); // 按照key以及路由来路径来导航,如果没找到会报错
              },
              child: Text("Go to second"),
            ),
          ),
        ),
      );
    } else if (settings.name == '/second') {
      return GetPageRoute(
        page: () => Center(
          child: Scaffold(
            appBar: AppBar(
              title: Text("Main"),
            ),
            body: Center(
              child:  Text("second")
            ),
          ),
        ),
      );
    }
  }
),

注意:尽量少用这种方式,因为在内存中维持多个导航堆栈比较消耗内存

转载自:https://juejin.cn/post/7227486312340095033
评论
请登录