還參考了一些其他文章:
在開始這篇文章之前我們先得明白,flutter這邊是不支援反射的,可能是google為了效能所做的取捨吧!但是隨著我們專案的開發越來越龐大,手動維護乙個路由 元素的檔案,一般是不太現實的,因此我們需要乙個類似工廠的方法,來自動建立我們的頁面例項,鑑於此我們必須來了解下註解----dart的註解。
註解是**級的配置,作用於編譯時或者是執行時,由於flutter目前不支援執行時的反射功能,因此我們必須在編譯期間就能獲取到註解的相關資訊。我們要根據這些註解資訊生成乙個對映表,然後將此對映表編譯到我們的工程裡,供我們的工程呼叫,(這裡的對映表通常是生成乙個dart檔案,以便在我們flutter裡使用)
註解的工作過程基本是這樣的,先對我們檔案進行掃瞄---->對檔案中的語法進行分析-------->提取註解------>篩選我們自己的註解----->將這些註解收集----->生成對映表。
dart提供了 build、analyser 、source_gen 這三個庫,其中source_gen是利用了其他兩個庫,給到了一層比較好的註解攔截的封裝。
build庫:整套資源檔案的處理
analyser庫:對dart檔案生成完備的語法結構
source_gen庫:提供註解元素的攔截
這裡source_gen是dart中比較複雜的庫,具體的有興趣的可以自己檢視source_gen的原始碼,這裡附上他的主頁:
在進行註解檔案生成前我們要注意下面幾個問題,問題
(1)整個工程我們只需要生成乙個配置對映檔案,因此我們需要在所有檔案掃瞄完畢以後在進行檔案生成。這個怎麼處理?
(2)source_gen 對乙個類只支援乙個註解,但是我們可能會存在多個url指向乙個頁面的情況,這個又需要怎麼處理?
解決點
(1)、我們需要將我們的註解分成兩類,一類是去註解我們的頁面即@***route()另乙個用於註解使用者自己的router,即@***router()routerbuilder 擁有routergenerator例項,負責@agreeroute()的解析routeparsebuilder擁有routeparsegenerator例項,負責@agreerouter()的解析
然後我們在專案的根目錄下新建乙個build.yaml檔案來控制我們的生成順序,最終只生成乙個對映檔案。
build.yaml配置檔案如下:
targets:(2)、在註解解析的過程中,我們對@***route註解的**,我們先返回null,對於我們@***router()註解過的**,我們返回寫入對映檔案。$default:
builders:
enabled: true
generate_for:
exclude: ['**.internal.dart']
enabled: true
generate_for:
exclude: ['**.internal.dart']
builders:
router_builder:
builder_factories: ['routerbuilder']
build_extensions:
build_to: source
route_parse_builder:
builder_factories: ['routeparsebuilder']
build_extensions:
build_to: source
import 'package:analyzer/dart/element/element.dart';3、(這裡的@agreerouter 註解是針對使用者做的進一步封裝)import 'package:build/build.dart';
import 'package:source_gen/source_gen.dart';
import 'agrrerouter.dart';
//解析被agreeroute註解過的介面
class routeparsegenerator extends generatorforannotation}
///生成agreerouter邏輯
class routergenerator extends generatorforannotation
@override
generateforannotatedelement(element element, constantreader annotation, buildstep buildstep)
}
使用的時候我們需要在我們的專案中先加入自己的路由檔案,如下所示:
我們生成的對映檔案是什麼樣子的呢?這裡需要我們自定義模板了,這裡附上自己的模板:import 'myarouter.internal.dart';
@***router()
class myarouter
return result.widget;
}}
const string routertpl="""我們最後會生成乙個類似這樣的檔案,routemap中儲存著我們的對映路徑(註解的url,對映到的類),createinstance含有我們傳遞的一些引數。}import '}}';
}class ***routerinternalimpl extends ***routerinternal }};
@override
***routeresult routerinternal(string url)
if(uri.host != 'flutter')
string path =uri.path;
if(path == null)
option.url = url;
option.parames = uri.queryparameters;
final type pageclass = routemap[path];
if(pageclass == null)
final dynamic classinstance = createinstance(pageclass, option);
return ***routeresult(widget: classinstance, ***routeresultstate: ***routeresultstate.found);
}catch(e)
} dynamic createinstance(type clazz, ***routeoption option) }}
}}""";
1、我們的庫中包含兩個註解 @***route() 用於註解你需要註解的類,
@***router()用於註解你專案中自己的進一步的封裝。
2、註解中的url 需要符合以下規範:
@***route(url:"***://flutter/pagea")url的scheme 必須是***,
url的host必須是flutter
url必須是兩級的
3、獲取我們定義過的註解的類的方法如下:
myarouter().getpage('***://flutter/pagea')myarouter()是我們工程中進一步封裝的路由類,使用起來會方便。
getpage()方法中傳進去url,就可以獲取我們註解的例項.
4、使用前需要在專案的pubspec.yaml中加入以下三方依賴
mustache4dart: ^3.0.0-dev.0.05、具體的例項可以參考上述的示例工程build_runner: ^0.9.1
source_gen: ^0.8.0
注 agreerouter目錄是基於source_gen 封裝的註解庫,使用的時候拷貝到你的工程目錄下,注意更改包名!
example目錄是使用示例,將myarouter.dart檔案拷貝到專案中後,
執行如下命令:
flutter packages pub run build_runner build會生成myarouter.internal.dart檔案 該檔案就是我們要的對映檔案
**示例:
document的一點思索
英語專八學前端,在家學習ing 今日看了一些關於效能提公升的東西 反思之前寫的兩篇文章 在每篇文章開頭都有以下 window.onload function this.newel function el this.frag function el par,el this.content functi...
一點一點進步
requestparam,是獲取前端傳遞給後端的引數,可以使get方式,也可以是post方式。若前端傳遞的引數和後端接收的引數名稱不一致,則必須要標註。pathvariable,是獲取get方式,url後面引數,進行引數繫結。1.裝箱就是講基本資料型別轉換為包裝類,拆箱就是自動將包裝類轉換為基本資料...
spring學習9 註解切面的一點
和基於xml的切面配置不同 註解切面需要乙個能處理 aspect 註解的處理器 annotationawareaspectautoproxycreator 它會自動 一些bean 這些bean的方法需要和 aspect註解的bean中的切點相匹配,而這些切點使用 pointcut定義的。實現該功能 ...