淺嘗Flutter(二)

淺嘗Flutter(一)
承接上文。

頁(yè)面路由框架

其實(shí)可以講的主要是Flutter的特性導(dǎo)致的一些架構(gòu)上的變化。
Android的界面跳轉(zhuǎn)主要涉及到系統(tǒng)層面的各個(gè)服務(wù)靠柑。

但是到了Flutter其實(shí)就沒(méi)有這些概念了,F(xiàn)lutter其實(shí)是單Activity架構(gòu)。
我另一個(gè)B端項(xiàng)目POS項(xiàng)目也采用的這種架構(gòu),作用很明顯塞茅,數(shù)據(jù)通信極其方便。缺點(diǎn)是頁(yè)面之間的路由維護(hù)會(huì)稍微復(fù)雜點(diǎn)季率。而且Flutter的Navigator用起來(lái)并不方便野瘦,一開(kāi)始項(xiàng)目對(duì)Navigator1.0做了一層封裝,初始化的參數(shù)定義特別死飒泻,很不方便鞭光,是一個(gè)List<String,Map<String,String>>,參數(shù)在傳遞過(guò)程中需要來(lái)回轉(zhuǎn)換泞遗,而且頁(yè)面標(biāo)識(shí)也不明顯惰许,非schema內(nèi)部跳轉(zhuǎn)也需要把參數(shù)進(jìn)行path轉(zhuǎn)換。

比如A--》B攜帶參數(shù){ "t1" : 1, "t2" : 2 }史辙,B定義為/test
那么跳轉(zhuǎn)path需要先拼接成/test?t1=1&t2=2汹买,然后到終端頁(yè)面還解析成了ArrayList<String,Map<String,Strign>>,這可太低效,且難以理解了聊倔。

屬實(shí)不好用晦毙,我覺(jué)的是一個(gè)很失敗的封裝,然后重新查閱了Flutter官網(wǎng)資料發(fā)現(xiàn)Flutter有一個(gè)Navigator2,采用了Page的概念去維護(hù)頁(yè)面棧方库,棧采用Arraylist<Page>结序,挺清晰的障斋。

所以在其他人開(kāi)發(fā)業(yè)務(wù)的同時(shí)我對(duì)項(xiàng)目的路由框架下層進(jìn)行了重構(gòu)纵潦。對(duì)外的接口類(lèi)不動(dòng),但是增加了一些可變參數(shù)垃环,減少改動(dòng)邀层。

class XXXNavigator{
  static Future navigateTo(BuildContext context, String pageDef,
      {bool clearStack = false,
      bool replace = false,
      String? clearToPageDef,
      Map<String, dynamic>? params}) {
    unfocus(context);
    if (globalDebugCtl) {
      print("Jump to $pageDef");
    }

    return CommonRouterDelegate.getInstance().addPage(context, pageDef, params,
        replace: replace,
        clearToPageDef: clearToPageDef,
        clearStack: clearStack);
  }

  static Future navigateTo(BuildContext context, String pageDef,
      {bool clearStack = false,
      bool replace = false,
      String? clearToPageDef,
      Map<String, dynamic>? params})

  //.....省略其他方法
}

CommonRouterDelegate是我實(shí)現(xiàn)Navigator的地方。

RouteObserver<PageRoute> routeObserver = RouteObserver<PageRoute>();

typedef RouterBuilder = BasePage? Function(
    String page, Map<String, dynamic>? params);

class CommonRouterDelegate extends RouterDelegate<CommonRoutePath>
    with ChangeNotifier, PopNavigatorRouterDelegateMixin<CommonRoutePath> {
  static CommonRouterDelegate? _instance;

  static CommonRouterDelegate getInstance() {
    _instance ??= CommonRouterDelegate._private();
    return _instance!;
  }

  CommonRouterDelegate._private();

  @override
  CommonRoutePath? get currentConfiguration => _currentConfiguration;

  @override
  final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
  CommonRoutePath? _currentConfiguration;

  var test = false;

  List<BasePage> pages = [
    const BasePage(child: SplashScreen()),
  ];

  @override
  Widget build(BuildContext context) {
    return Navigator(
      key: navigatorKey,
      pages: List.of(pages),
      observers: [routeObserver],
      onPopPage: (route, result) {
        if (!route.didPop(result)) {
          return false;
        }
        BasePage page = pages.removeLast();
        notifyListeners();
        _popCompleter[route.settings.name]?.complete(result);
        if (result is! LoadingPopEntity) {
          CommonRouterObserver.getInstance().onPageEnd(page);
        }
        //通知路由變化
        return true;
      },
    );
  }

  @override
  Future<void> setNewRoutePath(CommonRoutePath configuration) async {
    _currentConfiguration = configuration;
    notifyListeners();
  }

  final Map<String, Completer<dynamic>?> _popCompleter = {};

  //執(zhí)行指定行為并打開(kāi)某個(gè)頁(yè)面
  Future addPage(
      BuildContext context, String pageDef, Map<String, dynamic>? params,
      {bool replace = false,
      bool clearStack = false,
      String? clearToPageDef}) async {
    BasePage? page = getPage(pageDef, params);

    if (page != null) {
      if (replace) {
        pages.removeLast();
      }
      if (clearStack) {
        pages.clear();
      }
      if (clearToPageDef != null) {
        int index =
            pages.indexWhere((element) => element.name == clearToPageDef);
        if (index > 0) {
          pages = pages.sublist(0, index + 1);
        }
      }
      pages.add(page);
      notifyListeners();
      CommonRouterObserver.getInstance().onPageStart(page);
      _popCompleter[pageDef] = Completer<dynamic>();
      return await _popCompleter[pageDef]!.future;
    }
  }

  void clear() {
    pages.clear();
    notifyListeners();
  }

  void popUtil(BuildContext context, String clearToPageDef) {
    int index = pages.indexWhere((element) => element.name == clearToPageDef);
    while (index > 0 && index < pages.length) {
      BasePage page = pages.removeLast();
      // print("<<<<<<<<popUtil>clearToPageDef $page , index = $index");
      _popCompleter[page.name!] = Completer<dynamic>();
      _popCompleter[page.name]?.complete();
      CommonRouterObserver.getInstance().onPageEnd(page);
      PageRoute cur = ModalRoute.of(context) as PageRoute;
      routeObserver.didPop(cur, cur);
      index++;
    }
    notifyListeners();
  }

  BasePage<dynamic>? getPage(String pageDef, Map<String, dynamic>? params) {
    return baseModuleBuilder.call(pageDef, params) ??
        homeModuleBuilder.call(pageDef, params) ??
        accountModuleBuilder.call(pageDef, params) ??
        payModuleBuilder.call(pageDef, params);
  }
}

baseModuleBuilder遂庄,homeModuleBuilder寥院,accountModuleBuilder,payModuleBuilder等是我們的頁(yè)面工廠(chǎng)涛目,主要建立的是頁(yè)面和PageDef的關(guān)聯(lián)秸谢。
定義的PageDef中維護(hù)的是我們每個(gè)頁(yè)面的字符串路由描述凛澎。ModuleBuilder的作用還有對(duì)業(yè)務(wù)進(jìn)行分類(lèi)的作用」捞悖基于PageDef的映射關(guān)系我們實(shí)現(xiàn)頁(yè)面路由也是極其方便塑煎。

核心的幾個(gè)點(diǎn)主要是,頁(yè)面分發(fā)和頁(yè)面棧的維護(hù)臭蚁,以及Flutter的await機(jī)制的維護(hù)最铁,這個(gè)還挺好用的,比Android的startActivityForResult好用多了垮兑。
從主要方法addPage和Pop冷尉。
其中addPage中的幾個(gè)參數(shù)尤為重要,分為replace系枪,clearStack雀哨,clearToPageDef.
主要是實(shí)現(xiàn)了跳新頁(yè)面置換現(xiàn)在的頁(yè)面(啟動(dòng)頁(yè)面分發(fā)等場(chǎng)景),跳新頁(yè)面清棧(非游客模式的token實(shí)現(xiàn)場(chǎng)景)私爷,清理頁(yè)面到指定PageDef并打開(kāi)新頁(yè)面(主要是支付成功之后的下級(jí)頁(yè)面跳轉(zhuǎn)等場(chǎng)景)震束。

實(shí)際在使用一段時(shí)間之后,發(fā)現(xiàn)頁(yè)面嵌套await存在一些小問(wèn)題当犯,我知道是什么問(wèn)題垢村,前段時(shí)間太忙,加上代碼目前穩(wěn)定嚎卫,所以沒(méi)有來(lái)得及修復(fù)嘉栓,后面修復(fù)的更新一下。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拓诸,一起剝皮案震驚了整個(gè)濱河市侵佃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌奠支,老刑警劉巖馋辈,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異倍谜,居然都是意外死亡迈螟,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)尔崔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)答毫,“玉大人,你說(shuō)我怎么就攤上這事季春∠绰В” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)耘拇。 經(jīng)常有香客問(wèn)我撵颊,道長(zhǎng),這世上最難降的妖魔是什么惫叛? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任秦驯,我火速辦了婚禮,結(jié)果婚禮上挣棕,老公的妹妹穿的比我還像新娘译隘。我一直安慰自己,他們只是感情好洛心,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布固耘。 她就那樣靜靜地躺著,像睡著了一般词身。 火紅的嫁衣襯著肌膚如雪厅目。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天法严,我揣著相機(jī)與錄音损敷,去河邊找鬼。 笑死深啤,一個(gè)胖子當(dāng)著我的面吹牛拗馒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播溯街,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼诱桂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了呈昔?” 一聲冷哼從身側(cè)響起挥等,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎堤尾,沒(méi)想到半個(gè)月后肝劲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡郭宝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年辞槐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剩蟀。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡催蝗,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出育特,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布缰冤,位于F島的核電站犬缨,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏棉浸。R本人自食惡果不足惜怀薛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望迷郑。 院中可真熱鬧枝恋,春花似錦、人聲如沸嗡害。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)霸妹。三九已至十电,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間叹螟,已是汗流浹背鹃骂。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留罢绽,地道東北人畏线。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像良价,于是被迫代替她去往敵國(guó)和親象踊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容