Dart註解的一點思索

2021-10-01 07:20:33 字數 4058 閱讀 6863

還參考了一些其他文章:

在開始這篇文章之前我們先得明白,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:

$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

(2)、在註解解析的過程中,我們對@***route註解的**,我們先返回null,對於我們@***router()註解過的**,我們返回寫入對映檔案。

import 'package:analyzer/dart/element/element.dart';

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)

}

3、(這裡的@agreerouter 註解是針對使用者做的進一步封裝)

使用的時候我們需要在我們的專案中先加入自己的路由檔案,如下所示:

​import 'myarouter.internal.dart';

​@***router()

class myarouter

return result.widget;

}​}

我們生成的對映檔案是什麼樣子的呢?這裡需要我們自定義模板了,這裡附上自己的模板:

const string routertpl="""

}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) }}

}}​""";

我們最後會生成乙個類似這樣的檔案,routemap中儲存著我們的對映路徑(註解的url,對映到的類),createinstance含有我們傳遞的一些引數。

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.0

build_runner: ^0.9.1

source_gen: ^0.8.0

5、具體的例項可以參考上述的示例工程

注 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定義的。實現該功能 ...