Flutter路由管理代碼這么長怎么高效解決-創(chuàng)新互聯(lián)

這篇文章給大家介紹Flutter路由管理代碼這么長怎么高效解決,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

站在用戶的角度思考問題,與客戶深入溝通,找到萬榮網(wǎng)站設(shè)計(jì)與萬榮網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗(yàn)好的作品,建站類型包括:做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊雅安服務(wù)器托管、企業(yè)郵箱。業(yè)務(wù)覆蓋萬榮地區(qū)。

01  背景

在Flutter的業(yè)務(wù)開發(fā)過程中,F(xiàn)lutter側(cè)會逐漸豐富自己的路由管理。一個輕量的路由管理本質(zhì)上是頁面標(biāo)識(或頁面路徑)與頁面實(shí)例的映射。本文工程師將基于dart注解提供了一個輕量路由管理方案。

不論是在native與Flutter的混合工程,還是純Flutter開發(fā)的工程,當(dāng)我們實(shí)現(xiàn)一個輕量路由的時(shí)候一般會有以下幾種方法:

1. 較差的實(shí)現(xiàn),if-else的邏輯堆疊:

做映射時(shí)較差的實(shí)現(xiàn)是通過if-else的邏輯判斷把url映射到對應(yīng)的widget實(shí)例上。

class Router {
    Widget route(String url, Map params) {
        if(url == 'myapp://apage') {
            return PageA(url);
        } else if(url == 'myapp://bpage') {
            return PageB(url, params);
        }
    }
}

這樣做的弊端比較明顯:

1)每個映射的維護(hù)影響全局映射配置的穩(wěn)定性,每次維護(hù)映射管理時(shí)需要腦補(bǔ)所有的邏輯分支。

2)無法做到頁面的統(tǒng)一抽象,頁面的構(gòu)造器和構(gòu)造邏輯被開發(fā)者自定義。

3)映射配置無法與頁面聯(lián)動,把頁面級的配置進(jìn)行中心化的維護(hù),導(dǎo)致維護(hù)責(zé)任人缺失。

2. 一般的實(shí)現(xiàn),手動維護(hù)的映射表:

稍微好一點(diǎn)的是將映射關(guān)系通過一個配置信息和一個工廠方法來表現(xiàn)。

class Router {
    Map<String, dynamic> mypages = <String, dynamic> {
        'myapp://apage': 'pagea',
        'myapp://bpage': 'pageb'
    }
    Widget route(String url, Map params) {
        String pageId = mypages[url];
        return getPageFromPageId(pageId);
    }
    Widget getPageFromPageId(String pageId) {
        switch(pageId) {
            case 'pagea': return PageA();
            case 'pageb': return PageB();
        }
        return null;
    }

在Flutter側(cè)這種做法仍然比較麻煩,首先是問題3仍然存在,其次是由于Flutter目前不支持反射,必須有一個類似工廠方法的方式來創(chuàng)建頁面實(shí)例。

為了解決以上的問題,我們需要一套能在頁面級使用、自動維護(hù)映射的方案,注解就是一個值得嘗試的方向。我們的路由注解方案annotation_route應(yīng)運(yùn)而生,整個注解方案的運(yùn)行系統(tǒng)如圖所示:

Flutter路由管理代碼這么長怎么高效解決

讓我們從dart注解開始,了解這套系統(tǒng)的運(yùn)作。

02  dart注解

注解,實(shí)際上是代碼級的一段配置,它可以作用于編譯時(shí)或是運(yùn)行時(shí),由于目前Flutter不支持運(yùn)行時(shí)的反射功能,我們需要在編譯期就能獲取到注解的相關(guān)信息,通過這些信息來生成一個自動維護(hù)的映射表。那我們要做的,就是在編譯時(shí)通過分析dart文件的語法結(jié)構(gòu),找到文件內(nèi)的注解塊和注解的相關(guān)內(nèi)容,對注解內(nèi)容進(jìn)行收集,最后生成我們想要的映射表,這套方案的構(gòu)想如圖示:

Flutter路由管理代碼這么長怎么高效解決

在調(diào)研中發(fā)現(xiàn),dart的部分內(nèi)置庫加速了這套方案的落地。

03  Source_gen

dart提供了build、analyser、source_gen這三個庫,其中source_gen利用build庫和analyser庫,給到了一層比較好的注解攔截的封裝。從注解功能的角度來看,這三個庫分別給到了如下的功能:

  • build庫:整套資源文件的處理

  • analyser庫:對dart文件生成完備的語法結(jié)構(gòu)

  • source_gen庫:提供注解元素的攔截

這里簡要介紹下source_gen和它的上下游,先看看我們捋出來的它注解相關(guān)的類圖:

Flutter路由管理代碼這么長怎么高效解決

source_gen的源頭是build庫提供的Builder基類,該類的作用是讓使用者自定義正在處理的資源文件,它負(fù)責(zé)提供資源文件信息,同時(shí)提供生成新資源文件的方法。source_gen從build庫提供的Builder類中派生出了一個自己的builder,同時(shí)自定義了一套生成器Generator的抽象,派生出來的builder接受Generator類的集合,然后收集Generator的產(chǎn)出,最后生成一份文件,不同的派生builder對generator的處理各異。這樣source_gen就把一個文件的構(gòu)造過程交給了自己定義的多個Generator,同時(shí)提供了相對build庫而言比較友好的封裝。

在抽象的生成器Generator基礎(chǔ)上,source_gen提供了注解相關(guān)的生成器GeneratorForAnnotation,一個注解生成器實(shí)例會接受一個指定的注解類型,由于analyser提供了語法節(jié)點(diǎn)的抽象元素Element和其metadata字段,即注解的語法抽象元素ElementAnnotation,注解生成器即可通過檢查每個元素的metadata類型是否匹配聲明的注解類型,從而篩選出被注解的元素及元素所在上下文的信息,然后將這些信息包裝給使用者,我們就可以利用這些信息來完成路由注解。

04   annotation_route

在了解了source_gen之后,我們開始著手自己的注解解析方案annotation_route剛開始介入時(shí),我們遇到了幾個問題:

  1. 只需要生成一個文件:由于一個輸入文件對應(yīng)了一個生成文件后綴,我們需要避免多余的文件生成

  2. 需要知道在什么時(shí)候生成文件:我們需要在所有的備選文件掃描收集完成后再能進(jìn)行映射表的生成

  3. source_gen對一個類只支持了一個注解,但存在多個url映射到一個頁面
    在一番思索后我們有了如下產(chǎn)出

Flutter路由管理代碼這么長怎么高效解決

首先將注解分成兩類,一類用于注解頁面@ARoute,另一類用于注解使用者自己的router@ARouteRoot。routeBuilder擁有RouteGenerator實(shí)例,RouteGenerator實(shí)例,負(fù)責(zé)@ARoute注解;routeWriteBuilder擁有RouteWriterGenerator實(shí)例,負(fù)責(zé)@ARouteRoot注解。通過build庫支持的配置文件build.yaml,控制兩類builder的構(gòu)造順序,在routeBuilder執(zhí)行完成后去執(zhí)行routeWriteBuilder,這樣我們就能準(zhǔn)確的在所有頁面注解掃描完成后開始生成自己的配置文件。

在注解解析工程中,對于@ARoute注解的頁面,通過RouteGenerator將其配置信息交給擁有靜態(tài)存儲空間的Collector處理,同時(shí)將其輸出內(nèi)容設(shè)為null,即不會生成對應(yīng)的文件。在@ARoute注解的所有頁面掃描完成后,RouteWriteGenerator則會調(diào)用Writer,它從Collector中提取信息,并生成最后的配置文件。對于使用者,我們提供了一層友好的封裝,在使用annotation_route配置到工程后,我們的路由代碼發(fā)生了這樣的變化:

使用前:

import 'testa.dart'
import 'testb.dart'
import 'testc.dart'
import 'testd.dart'
import 'teste.dart'
import 'testf.dart'
 class Router {
    Widget pageFromUrlAndQuery(String urlString, Map<String, dynamic> query) {
        if(urlString == 'myapp://testa') {
            return TestA(urlString, query);
        } else if(urlString == 'myapp://testb') {
            String absoluteUrl = Util.join(urlString, query);
            return TestB(url: absoluteUrl);
        } else if(urlString == 'myapp://testc') {
            String absoluteUrl = Util.join(urlString, query);
            return TestC(config: absoluteUrl);
        } else if(urlString == 'myapp://testd') {
            return TestD(PageDOption(urlString, query));
        } else if(urlString == 'myapp://teste') {
            return TestE(PageEOption(urlString, query));
        } else if(urlString == 'myapp://testf') {
            return TestF(PageFOption(urlString, query));
        }
        return DefaultWidget;
    }
 }

使用后:

import 'package:annotation_route/route.dart';
 class MyPageOption {
    String url;
    Map<String, dynamic> query;
    MyPageOption(this.url, this.query);
 }
 class Router {
    ARouteInternal internal = ARouteInternalImpl();
    Widget pageFromUrlAndQuery(String urlString, Map<String, dynamic> query) {
        ARouteResult routeResult = internal.findPage(ARouteOption(url: urlString, params: query), MyPageOption(urlString, query));
        if(routeResult.state == ARouteResultState.FOUND) {
            return routeResult.widget;
        }
        return DefaultWidget;
    }
 }

關(guān)于Flutter路由管理代碼這么長怎么高效解決就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

當(dāng)前題目:Flutter路由管理代碼這么長怎么高效解決-創(chuàng)新互聯(lián)
文章轉(zhuǎn)載:http://muchs.cn/article42/dpphhc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站企業(yè)建站、靜態(tài)網(wǎng)站、網(wǎng)站設(shè)計(jì)公司、全網(wǎng)營銷推廣品牌網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營