flutter 一個簡單的Route Helper/Navigator Helper

在flutter中 route是一個繞不開,必須面對,且很經常使用東西bash

Route就是路由,顧名思義,負責你頁面間的跳轉async

不想看代碼和思路分析的直接copy了拿去用就行 沒有啥外部依賴,只須要注意_rootRoute 後面的字符串須要和initialRoute 對應便可工具

路由又分靜態和動態路由ui

靜態就是不須要傳參數的,這樣的路由能夠直接定義在MaterialApp/WidgetsApp 裏 這樣能夠經過Navigator.pushNamed調用spa

動態的就是傳入一個PageRoute, 一般是一個MaterialPageRoute 或者CupertinoPageRoute,或者你若是有自定義的有可使用3d

這裏我使用一個個人工具類來實現跳轉,由於大部分狀況下,工程中的路由都是動態的,也就是須要傳參數的,因此工具類中只包含了使用Widget相關的方案code

import 'dart:async';

import 'package:flutter/material.dart';

class RouteHelper {
  static Future<T> pushWidget<T>(
    BuildContext context,
    Widget widget, {
    bool replaceRoot = false,
    bool replaceCurrent = false,
  }) {
    return pushRoute(
      context,
      MaterialPageRoute(builder: (ctx) => widget),
      replaceRoot: replaceRoot,
      replaceCurrent: replaceCurrent,
    );
  }

  static Future<T> pushRoute<T>(
    BuildContext context,
    PageRoute<T> route, {
    bool replaceRoot = false,
    bool replaceCurrent = false,
  }) {
    assert(!(replaceRoot == true && replaceCurrent == true));
    if (replaceRoot == true) {
      return Navigator.pushAndRemoveUntil(
        context,
        route,
        _rootRoute,
      );
    }
    if (replaceCurrent == true) {
      return Navigator.pushReplacement(context, route);
    }
    return Navigator.push(context, route);
  }
}

var _rootRoute = ModalRoute.withName("home");
複製代碼

解析一下這個類,有兩個方法,一個是接受PageRoute,一個是接收Widgetcdn

接收Widget的是講Widget包裝爲MaterialPageRoute,而後傳給另外一個方法對象

另外一個方法中包含3種狀況,一種是替換根節點,一種是替換當前頁面(關閉當前,且開啓新頁面),還有一種就是日常的push(即 不關閉當前,直接開啓新的)blog

根據傳參不一樣而有所不一樣

有一個_rootRoute變量,這個變量的目的是用於替換根節點,'home'是我定義在MaterialApp裏的initialRoute,這樣一一對應才能確保替換根節點


固然這個類也能夠繼續擴展,好比將routes定義在內,而後傳route name 參數,接着經過routes來提取出named對應的Widget/Route 接着傳入pushRoute方法進行跳轉便可


這個簡便的Helper還有另外一個好處,就是能夠方便後續批量替換Route實現,好比有一天你想自定義一個PageRoute,不使用MaterialRoute ,那麼你只須要替換以下如所示的部分便可

image.png


固然還能夠有別的擴展方法來支持named 好比查看Navigator的源碼發現pushNamed,就是經過widget.onGenerateRoute方法獲取到route的,我這裏直接在helper中寫就行了

image.png


Helper 寫完了,咱們看看使用的方法 使用起來也很簡單

好比強登錄應用

void  _login() {
    RouteHelper.pushWidget(context, HomeRootPage(), replaceRoot: true);
  }
複製代碼

這裏登陸成功後,我直接替換了root節點,而後根路由就變成了主頁面

void _forgetPwd() {
    RouteHelper.pushWidget(context, ForgetPwdPage());
  }

  void _register() {
    RouteHelper.pushWidget(context, RegiseterPage());
  }
複製代碼

忘記密碼和註冊都基於登陸在作,最終要返回登陸,因此這裏用普通的調用方法

_register() {
    RouteHelper.pushWidget(
      context,
      RegisterSuccessPage(),
      replaceCurrent: true,
    );
  }
複製代碼

註冊成功後我這裏有一個單獨的註冊成功頁,寫了一些註冊後的注意事項,而返回又應該直接返回到登陸頁面,因此這裏我須要替換掉當前的頁面,只用replaceCurrent 便可


固然方法接受返回值也是容許的

_orderDetail(String item) async {
    //todo 查看訂單詳情
    var result = await RouteHelper.pushWidget<bool>(context, OrderDetailPage(id: item));
    if (result == true) {
      _refresh();
    }
  }
複製代碼

這裏若是在詳情頁買了東西/加到購物車,回到主頁面,是要刷新頁面的,因此咱們接收返回值,而後判斷

小tips:這裏之因此用result == true 而不是 if(result) 是由於dart中 bool是有3個值的 true false null if(result==true) 能夠將result 爲 null的狀況規避掉,提高代碼健壯性,這個不得不說是dart 徹底面向對象形成的反作用

相關文章
相關標籤/搜索